Resource 기반 정책 예제(REST API 보호)

Keycloak에서 제공하는 Resource 기반 정책은 API 엔드포인트 자체를 자원(Resource)으로 정의하고, 각 자원에 대해 접근 가능한 범위(Scope)를 설정함으로써 세밀한 접근 제어를 가능하게 한다. 이를 통해 REST API를 보호할 수 있으며, 사용자는 각 요청 시 필요한 범위(Scope)를 만족하는 권한(Authorization)이 있어야만 자원에 접근할 수 있다.

Resource와 Scope 정의

Keycloak의 Admin Console에서 자원을 정의하려면, 먼저 클라이언트(Client) 타입을 bearer-only 혹은 confidential로 설정한 애플리케이션(혹은 API 서버)에 접근한다. 그 후 Authorization 탭 아래의 Resources 메뉴에서 자원과 범위를 설정할 수 있다.

  • Resource Name: 보호하려는 대상의 이름을 지정한다. 예를 들어 “employee-api”와 같은 식으로 REST API에 대한 범용적인 자원 이름을 지을 수 있다.

  • URI: 해당 자원에 연결된 API 엔드포인트 경로를 지정한다. 예: /employees/*

  • Scopes: 해당 자원에 허용할 구체적인 범위를 정의한다. 예: read, write, delete

Resource는 특정 URI에 대한 접근 권한을 정의하고, Scope는 그 자원에 대해 수행할 수 있는 구체적인 행위를 묘사한다. 예를 들어, “employee-api”라는 Resource에 read, write 스코프를 정의했다면, GET /employees/* 요청에는 read 스코프가 필요하고, POST /employees 요청에는 write 스코프가 필요하다고 설계할 수 있다.

Policy 생성

Resource와 Scope를 정의했다면, 이제 사용자(또는 그룹, 역할 등)가 어떤 조건을 만족할 때 접근을 허용할지를 결정하는 Policy를 작성해야 한다. Keycloak은 다음과 같은 다양한 정책 타입을 지원한다.

  • Role-based Policy: 특정 역할(Role)에 부여된 사용자에게만 권한 부여

  • User-based Policy: 특정 사용자에게만 권한 부여

  • Group-based Policy: 특정 그룹(Group)에 속한 사용자에게만 권한 부여

  • JavaScript-based Policy: 자바스크립트 로직으로 동적 정책 결정

  • Time-based Policy: 특정 시간대 또는 요일에만 허용

  • 기타 커스텀 방식 등

예를 들어, 사내 admin 역할을 가진 사용자만 write 스코프를 사용할 수 있도록 하고, user 역할을 가진 사용자는 read 스코프만 가능하도록 정책을 구성할 수 있다. 이때 Admin Console의 Policies 메뉴에서 새 Policy를 생성하고, “role” 타입을 사용해 다음과 같이 만든다.

  • Policy 1

    : admin-role-policy

    • Type: Role

    • Allowed Role: admin

  • Policy 2

    : user-role-policy

    • Type: Role

    • Allowed Role: user

Permission 설정

Keycloak에서 Permission은 Resource, Scope, Policy를 묶어 “정말 접근을 허용할 것인가?”를 최종적으로 결정하는 객체이다. 예를 들어 “employee-api” Resource에 대해 write 스코프를 admin-role-policy가 허용하도록, read 스코프는 user-role-policy가 허용하도록 설정할 수 있다.

Admin Console의 Permissions 메뉴에서 “Create permission”을 선택한 뒤, 다음과 같이 구성한다.

  • Resource: employee-api

  • Scopes: write

  • Apply Policy

    : admin-role-policy

    • 이 Permission은 /employees/* 자원에 대한 write 스코프를 사용하려는 요청을 admin 역할인 사용자에게만 허용한다.

또 다른 Permission을 만들어 read 스코프의 접근을 user-role-policy 정책으로 허용할 수 있다.

애플리케이션 구성

Keycloak에서 Resource와 Scope, Policy, Permission 구성이 끝났다면, 실제 애플리케이션(REST API 서버)에서 Keycloak의 Access Token 또는 RPT(Authorization 토큰)를 검증하는 로직을 적용한다.

  1. 클라이언트(사용자 에이전트) 토큰 획득

    • 사용자는 Keycloak에 로그인하여 Access Token 또는 RPT를 발급받는다.

  2. API 요청 시 토큰 전송

    • 클라이언트는 REST API를 호출할 때, Authorization: Bearer <TOKEN> 형태로 토큰을 헤더에 실어 보낸다.

  3. 서버에서 토큰 검증

    • REST API 서버는 Keycloak의 공개 키(또는 Keycloak Adapter)를 이용해 토큰의 유효성(서명, 만료 시간 등)을 검증한다.

    • 만약 Keycloak Policy Enforcer(어댑터)를 사용한다면, 엔드포인트별 매핑된 Resource와 Scope에 자동으로 접근할 수 있는지 확인한다.

    • 어댑터가 없는 환경이라면 서버가 직접 Keycloak의 /userinfo 또는 Token Introspection 엔드포인트를 호출하여 토큰의 유효성과 Scope 정보를 확인하고, 허용된 Scope에 따라 요청을 처리한다.

API 서버가 자바(Spring Boot) 환경이라면, Keycloak Spring Boot Adapter를 통해 자원 보호를 자동화할 수 있다. 엔드포인트별 Security 설정에 Scope를 매핑하면, Spring Security 필터 단계에서 Keycloak Adapter가 사용자의 토큰에 필요한 Scope가 있는지 검사한다. .NET, Node.js 등의 환경에서도 유사하게 Keycloak Adapter 또는 Token 검증 라이브러리를 통해 구현 가능하다.

API 보호 동작 확인

  1. 토큰 없는 요청

    • Authorization 헤더 없이 /employees 엔드포인트에 접근하면 Keycloak 또는 API 서버가 401(Unauthorized) 혹은 403(Forbidden)을 반환한다.

  2. 권한 없는 사용자 토큰

    • 예를 들어, read 스코프만 가진 사용자 토큰으로 POST /employees(= write 스코프 필요)를 호출하면, 403(Forbidden)이 반환된다.

  3. 적절한 스코프를 가진 사용자 토큰

    • admin 역할이 부여된 사용자(즉, write 스코프)가 발급받은 토큰을 헤더에 포함해 POST /employees를 호출하면 200(OK) 또는 201(Created) 등의 성공 응답이 온다.

이와 같은 방식으로 Keycloak의 Resource 기반 정책을 이용하면, REST API를 스코프 단위로 세분화해 안전하게 보호할 수 있다. 자원, 스코프, 정책, 권한을 잘 설계함으로써, 애플리케이션 도메인 요구사항에 맞는 접근 제어를 구현할 수 있다.

Last updated