본문으로 건너뛰기
버전: Latest(v3.0) 🔥

MCP Oauth2

1. 소개

mcp-oauth2OAuth2/OIDC(주로 Keycloak 사용)를 활용하여 MCP HTTP endpoints를 보호하는 Kong plugin/policy입니다. mcp-oauth2는 다음과 같은 기능을 제공합니다.

  • Client discovery: /.well-known/oauth-protected-resource (RFC 9728)를 통해 MCP 클라이언트가 Authorization Server와 지원되는 범위를 확인할 수 있습니다.
  • JWT access-token validation: iss(issuer), aud(audience), 그리고 JWKS를 사용한 서명을 검증합니다.
  • (선택 사항) authorization by scope/role: mcp_scopes와 같은 클레임을 활용하여 범위 MCP JSON-RPC 메서드에 매핑해 접근 권한을 제어할 수 있습니다.

2. APIM 콘솔 설정

단계 1: 백엔드를 MCP 서버로 설정하여 신규 API를 생성합니다.

MCP 서버: http://wikipedia-mcp.기본값.svc.cluster.local:8080/mcp 

VS Code에서 이 API를 통해 MCP 서버에 접근해야 하므로, VS Code는 추가 경로 세그먼트가 있는 URL을 지원하지 않기 때문에 Base Path를 “/” (경로 없음)으로 설정합니다.

단계 2: mcp-oauth2 정책을 해 API에 적용합니다.

단계 3: mcp-oauth2 정책 버튼을 클릭하여 아래의 구성 세부정보를 표시합니다.

Section 1: PROTECTED RESOURCE METADATA (RFC 9728)

필드유형필수 여부기본값설명
Protected Resource Metadata PathstringYes/.well-known/oauth-protected-resource• 플러그인이 RFC 9728 보호된 리소스 메타데이터 문서를 제공하는 URL 경로입니다.
• MCP 클라이언트는 이를 사용하여 인증 서버와 지원되는 범위를 발견합니다.
• 거의 변경할 필요가 없습니다.
Authorization Servers:
  • 신뢰할 수 있는 인증 서버의 배열입니다. 이 MCP 엔드포인트에 대한 토큰을 발급하는 각 Keycloak 영역(또는 다른 OAuth2 공급자)마다 하나의 항목을 추가합니다.
  • 더 많은 항목을 추가하려면 +를 클릭합니다.
필드유형필수 여부설명
UrlstringYes인증 서버의 공개 URL (클라이언트가 인증 및 토큰 발급을 위해 접근하는 주소)입니다.
• jwks_uri가 상대 경로일 경우, JWKS URL을 구성하기 위한 기본 URL로도 사용됩니다..

예시: https://keycloak-demo.apimags.skcloud.io/realms/master
IssuerstringYes• JWT의 iss (발급자) 클레임과 일치합니다.
• 토큰의 발급자가 일치하지 않으면 거부됩니다.
정확히 string이 일치해 하며, 프로토콜, 호스트, 포트 및 경로(끝에 슬래시 없음)를 포함해야 합니다.
확인 위치: {realm-url}/.well-known/openid-configuration → issuer 필드.
AudiencestringYes• JWT의 aud (audience) 클레임과 일치합니다.
• 다른 서비스용으로 설정된 토큰이 수락되지 않도록 방지합니다. 
• Keycloak Audience Mapper에 설정된 값과 정확히 일치해야 합니다.
JWKS URIstringYes• 플러그인이 JWT 서명을 검증하기 위해 인증 서버의 공개 서명 키(JWKS)를 가져오는 엔드포인트입니다.
Relative path (Url에 추가됨): /.well-known/jwks.json 일 수도 있고 Absolute URL (그대로 사용됨): https://keycloak-demo.ags.cloudzcp.net/realms/master/protocol/openid-connect/certs일 수도 있습니다. Kong이 클라이언트와 동일한 호스트명을 통해 인증 서버에 접근할 수 없는 경우(예: Docker/Kubernetes 네트워킹 환경), Absolute URL 사용을 권장합니다. (예: Docker/k8s 네트워킹).  기본값: /.well-known/jwks.json
Section 2: SUPPORTED OAUTH2 SCOPES 

필드유형필수 여부기본값설명
Scopes SupportedstringYes비어 있음보호된 리소스 메타데이터 문서에 나열되어 클라이언트가 어떤 범위를 요청해야 하는지 안내합니다. 이는 정보 제공용일 뿐이며, 클라이언트 디스커버리를 돕지만 실제로 접근을 강제하지는 않습니다.
각 범위를 입력하고 Enter를 눌러 추가할 수 있습니다.

예시: mcp:tools
Section 3: TOKEN VALIDATION

필드유형필수 여부기본값설명
Authorization Header NamestringYesAuthorization • Authorization Header Name = 서버/플러그인이 토큰 검증을 위해 액세스 토큰을 찾기 위해 읽을 HTTP 헤더 이름입니다.
• 일반적으로 Authorization으로 유지합니다.
• 클라이언트는 다음과 같이 토큰을 전송합니다: Authorization: Bearer <access_token>
• API가 다른 헤더에서 토큰을 기대하는 경우에만 변경합니다.
• (예: X-Authorization).

Section 4: UPSTREAM TOKEN FORWARDING 

필드유형필수 여부기본값설명
Forward Authorization HeaderbooleanNofalse• false - MCP 서버로 전달하기 전에 Authorization 헤더를 제거합니다 (더 안전한 기본값).
• true - Bearer <token> 헤더를 업스트림 MCP 서버로 전달합니다.
• MCP 서버가 토큰을 읽어야 하는 경우 활성화합니다 (예: 사용자 신원 또는 클레임을 추출하기 위해).
Section 5: ACL

FieldType필수 여부기본값설명
Enable ACLbooleanNofalse• false - 유효한 토큰은 모든 MCP 메서드에 대한 접근을 허용합니다 (토큰 검증은 여전히 발생합니다).
• true - 토큰을 검증한 후, 플러그인은 특정 JSON-RPC 메서드가 허용되는지 결정하기 위해 토큰의 범위/역할을 Scope Method Mapping와 비교합니다.
ACL ClaimstringNoscope• 사용자의 권한을 포함하는 JWT 클레임의 이름입니다. 플러그인은 이 클레임을 읽고 ACL 검사를 위해 그 값을 사용합니다.
• 일반적인 값:
→ mcp_scopes - Keycloak Protocol Mapper의 커스 클레임

⚠️ Keycloak Protocol Mapper에서 토큰 클레임 이름을 정확히 일치해야 합니다.
Section 6: SCOPE METHOD MAPPING

각 범위/역할을 해당 범위가 호출할 수 있는 MCP JSON-RPC 메서드 목록에 매핑합니다. Enable ACL가 true일 때만 유효합니다.

필드유형필수 여부설명
ScopestringYes (per entry)범위/역할 이름입니다. ACL Claim에서 JWT 클레임에 지정된 값과 일치해야 합니다.
예시: mcp:tools
Methodsarray of stringsYes (per entry)이 범위에서 호출할 수 있는 MCP JSON-RPC 메서드 이름입니다. 각 메서드 이름을 입력하고 Enter를 눌러 추가합니다.
예시: tools/list, tools/call

⚠️ ACL이 활성화되어 있지만 Scope Method Mapping이 비어 있는 경우: 모든 요청이 거부됩니다. 최소한 하나의 매핑을 구성해야 합니다.

💡 권한은 누적된 경우: 사용자는 메서드를 허용하는 하나의 범위만 필요합니다. 토큰의 어떤 범위라도 메서드를 허용하면 접근이 허용됩니다.

Section 7: TIMEOUTS & CACHING
필드유형필수 여부기본값설명
Token Cache TTL (s)numberNo300검증된 토큰이 Kong의 공유 메모리에 캐시되는 시간(초)입니다. 이 기간 동안 동일한 토큰으로 반복 요청을 하면 JWT 디코딩 및 서명 검증을 건너뜁니다.
캐시된 경우에도 플러그인은 매 요청마다 JWT exp 클레임을 재확인하고 만료된 토큰을 무효화합니다.
HTTP Timeout (ms)numberNo10000인증 서버에서 JWKS(공개 서명 키)를 가져오기 위한 HTTP 요청의 타임아웃(밀리초)입니다. 인증 서버가 이 시간 내에 응답하지 않으면 토큰 검증이 실패합니다.
• 인증 서버가 느린 네트워크에 있거나 콜드 스타트 중인 경우 증가시킵니다.
• 인증 서버에 접근할 수 없을 때 더 빠른 실패를 위해 감소시킵니다.

3. Keycloak 설정

3.1. Keycloak OAuth2 Foundation

이 단계는 MCP 클라이언트가 인증 서버를 발견하고 올바른 audience으로 토큰을 얻을 수 있도록 Keycloak을 구성합니다.

3.1.1 클라이언트 범위 생성

작동 방식: 클라이언트가 요청할 수 있는 이름이 지정된 스코프(named scope)를 생성합니다. 클라이언트가 해당 스코프를 요청하면, Keycloak은 이를 토큰에 포함시키며, 해당 스코프에 연결된 mapper들도 함께 실행됩니다.

단계 1: Keycloak Admin → Client scopes → Create client scope로 이동

단계 2: 데이터 입력 → Save 클릭

필드설명
Namemcp:tools귀하의 MCP 클라이언트가 요청할 범위 이름
ProtocolOpenID Connect표준 OAuth2/OIDC 프로토콜
Display on consent screenON클라이언트가 로그인 중 요청하는 내용 표시
Consent screen textAccess MCP tools사용자에게 읽기 쉬운 설명
Include in token scopeON범위 값이 JWT 범위 클레임에 나타나도록 보장

3.1.2 Audience Mapper 추가

동작 방식: 액세스 토큰에 aud(audience) 클레임을 추가합니다. 플러그인은 토큰의 audience이 구성된 값과 일치하는지 검증합니다 - 이는 다른 서비스에 대해 발급된 토큰이 귀하의 MCP 엔드포인트에서 수락되는 것을 방지합니다.

단계 1: 방금 생성한 mcp:tools scope로 이동 → Mappers 탭 → Configure a new mapper → Audience 선택

단계 2: 데이터 입력 → Save 클릭
필드설명
Nameaudience-config이 Mapper에 대한 설명 이름
Included Custom Audienceaudience-nameKong 플러그인 구성의 audience 필드와 일치해야 합니다
Add to access tokenON플러그인은 ID 토큰이 아닌 액세스 토큰을 읽습니다.
Add to ID tokenOFFID 토큰은 클라이언트 앱을 위한 것이며, 리소스 서버를 위한 것이 아닙니다.

3.1.3. 새 클라이언트 만들기

동작 방식: MCP 클라이언트가 Keycloak에 연결할 수 있도록 클라이언트를 만듭니다.

단계 1: Clients → Create client로 이

단계 2: Client ID 데이터 입력 → Next 클릭

설명
Client IDMcp-client클라이언트 ID
단계 3: Config → Next 클릭

단계 4: Config → Save 클릭

3.2. Keycloak: 그룹 기반 ACL 설정

이 섹션에서는 사용자별로 서로 다른 MCP 권한을 부여하기 위한 세분화된 접근 제어(fine-grained access control)를 설정합니다. 전체 아키텍처는 다음과 같습니다.

Groups → Realm Roles → Protocol Mapper → "mcp_scopes" JWT claim → ACL

3.2.1. Realm Roles 만들기

동작 방식: 명명된 권한 계층입니다. 각 역할은 사용자가 호출할 수 있는 MCP 메서드 집합을 나타냅니다. 역할 이름은 JWT mcp_scopes 클레임에 나타납니다.

단계 1: Realm roles → Create role (repeat for each)로 이동

단계 2: 각 role마다 Role name만 입력한 후 Save를 클릭하면 됩니다. 추가적인 설정은 필요하지 않습니다.
Role Name용도예시 MCP Methods
mcp:tools도구 접근을 위함tools/list
mcp:resources리소스 접근을 위함resources/read

3.2.2. 그룹 만들기

동작 방식: 사용자에 대한 조직적 컨테이너입니다. 사용자별로 역할을 할당하는 대신, 그룹에 역할을 할당하고 그 후 사용자를 그룹에 추가합니다.

단계 1:  Groups → Create group로 이동

단계 2: sub-group를 생성하려면 부모 그룹 클릭 → 자식 그룹 생성
Group NameDescription
mcp-member기본 회원 접근
mcp-admin모든 MCP 도구 및 리소스에 대한 전체 접근

3.2.3. 그룹에 역할 할당하기

단계 1: Groups으로 이동 → 하나의 group 클릭 → Role mapping 탭 클 → Assign role 선택
GroupRoles to Assign
Mcp-adminmcp:tools, mcp:resources
Mcp-membermcp:tools

Assign

3.2.4. Protocol Mapper 만들기 (mcp_scopes 클레임)

동작 방식: Keycloak에 사용자의 영역 역할(필터링된 mcp: 접두사 포함)을 액세스 토큰의 mcp_scopes라는 사용자 정의 클레임으로 포함하도록 지시합니다. 이는 Kong 플러그인이 ACL 결정을 내리기 위해 읽는 클레임입니다. 단계 4: Client scopes → mcp:tools → Mappers  → Add mapper 클 → By configuration 선택 → User Realm Role 선택

단계 2: 데이터 입력

필드설명
Namemcp-scopes-mapper설명 이름
Mapper TypeUser Realm Role사용자의 영역 역할을 토큰 클레임에 매핑
Token Claim Namemcp_scopesKong 플러그인 구성의 acl_claim과 일치해야 함
Multi값dON사용자는 여러 역할을 가질 수 있음
Add to access tokenON플러그인이 액세스 토큰을 읽음
Add to ID tokenOFF리소스 서버 검증에 필요하지 않음
Add to userinfoOFF필요하지 않음

Critical: Token Claim Name (mcp_scopes)는 Kong 플러그인 구성의 acl_claim 필드와 일치해야 합니다. 불일치가 발생하면 플러그인이 토큰에서 권한을 찾을 수 없습니다.

3.2.5. 사용자 그룹에 추가

단계 1: Users로 이동 → 하나의 user 클릭 → Groups 탭으로 이동 → Join group 클릭 → 적절한 그룹을 선택

단계 2: Join 클릭
UserGroupResulting JWT mcp_scopes
canhng1Mcp-memberMcp:tools, Mcp:resources
adminmcp-adminMcp:resources

4. Visual Studio Code를 사용한 테스트

4.1. Kong 프록시를 로컬로 포워딩

4.2. 새로운 MCP 서버 만들기

VS Code를 실행한 후, Ctrl + Shift + P를 누르고 MCP: Add server…를 선택합니다.그 다음 HTTP를 선택하고 http://localhost:8100을 입력합니다.Visual Studio Code 내에서 사용할 고유한 서버 이름을 지정합니다.이제 mcp.json 파일에서 아래와 같은 항목을 확인할 수 있습니다:

4.3. 서버 시작 및 Keyloak 인증으로 모의 MCP 서버에 연결하기

로그인 성공하고 22개의 도구로 Mock MCP 서버에 연결되었습니다.