MCP Oauth2
1. Giới thiệu
mcp-oauth2 là một Kong plugin/policy bảo vệ MCP HTTP endpoints bằng cách sử dụng OAuth2/OIDC (thường là với Keycloak).
Nó cung cấp:
- Client discovery qua /.well-known/oauth-protected-resource (RFC 9728), để các khách hàng MCP có thể tìm hiểu về máy chủ ủy quyền và các phạm vi được hỗ trợ.
- JWT access-token validation: kiểm tra iss (người phát hành), aud (đối tượng), và chữ ký bằng cách sử dụng JWKS.
- (Tùy chọn) authorization by scope/role (ví dụ: từ một yêu cầu như mcp_scopes) bằng cách ánh xạ các phạm vi đến các phương thức MCP JSON-RPC được phép.
2. Cài đặt Bảng điều khiển APIM
Bước 1: Tạo một API mới với backend được thiết lập đến một máy chủ MCP.
Máy chủ MCP: http://wikipedia-mcp.default.svc.cluster.local:8080/mcp
Bởi vì chúng ta cần truy cập máy chủ MCP thông qua API này từ VS Code, và VS Code không hỗ trợ các URL với một đoạn đường bổ sung, chúng ta thiết lập Đường dẫn Cơ sở = “/” (không có đường dẫn).

Bước 2: Áp dụng chính sách mcp-oauth2 cho API.

Bước 3: Nhấp vào nút chính sách mcp-oauth2 để hiển thị chi tiết cấu hình bên dưới.
Section 1: PROTECTED RESOURCE METADATA (RFC 9728)
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| Protected Resource Metadata Path | string | Yes | /.well-known/oauth-protected-resource | • Đường dẫn URL nơi plugin phục vụ tài liệu Metadata Tài nguyên Bảo vệ RFC 9728. • Các khách hàng MCP lấy cái này để phát hiện các máy chủ ủy quyền và các phạm vi được hỗ trợ. • Hầu như không bao giờ cần thay đổi. |
- Một mảng các máy chủ ủy quyền đáng tin cậy. Thêm một mục cho mỗi Keycloak vùng (hoặc nhà cung cấp OAuth2 khác) phát hành token cho điểm cuối MCP này.
- Nhấp vào + để thêm nhiều mục hơn.
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| Url | string | Yes | • public URL of the authorization server (nơi khách hàng đến để xác thực/lấy token).
• Nó cũng là base URL for building the JWKS URL khi jwks_uri là một đường dẫn tương đối.
Example: https://keycloak-demo.apimags.skcloud.io/realms/master | | Issuer | string | Yes | • Được so khớp với tuyên bố iss (nhà phát hành) trong JWT.
• Nếu nhà phát hành của token không khớp, nó sẽ bị từ chối.
• Phải là một exact string match • bao gồm giao thức, máy chủ, cổng và đường dẫn (không có dấu gạch chéo ở cuối).
• Find it at:<realm-url>/.well-known/openid-configuration → trường nhà phát hành. | | Audience | string | Yes | • Được so khớp với tuyên bố aud (khán giả) trong JWT.
• Ngăn chặn các token dành cho các dịch vụ khác được chấp nhận.
• Must exactly match giá trị được cấu hình trong Keycloak Audience Mapper. | | JWKS URI | chuỗi | Có | • Điểm cuối nơi plugin lấy các khóa ký công khai của máy chủ ủy quyền (JWKS) để xác minh chữ ký JWT.
• Có thể là: Relative path (thêm vào Url): /.well-known/jwks.json Absolute URL (sử dụng như là): https://keycloak-demo.apimags.skcloud.io /realms/master/protocol/openid-connect/certs Sử dụng URL tuyệt đối khi Kong không thể đến máy chủ xác thực qua cùng một tên miền như các client (ví dụ: mạng Docker/k8s). Default: /.well-known/jwks.json |

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| Scopes Supported | mảng các chuỗi | Có | trống | Được liệt kê trong tài liệu Metadata Tài nguyên Bảo vệ để cho các client biết các phạm vi nào cần yêu cầu. Điều này là informational only • nó hướng dẫn việc khám phá client nhưng không áp đặt bất kỳ điều gì. Gõ từng phạm vi và nhấn Enter để thêm nó. Example: mcp:tools |

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| Authorization Header Name | chuỗi | Có | Ủy quyền | • Authorization Header Name = tên tiêu đề HTTP mà máy chủ/plugin của bạn sẽ đọc để tìm mã thông báo truy cập cho việc xác thực mã thông báo. • Thường giữ nó như Authorization. • Các client sau đó gửi mã thông báo như:Authorization: Bearer <access_token>• Chỉ thay đổi nếu API của bạn mong đợi mã thông báo trong một tiêu đề khác • (ví dụ: X-Authorization). |
Section 4: UPSTREAM TOKEN FORWARDING

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| Forward Authorization Header | boolean | Không | false | • false - Loại bỏ tiêu đề Authorization trước khi chuyển tiếp đến máy chủ MCP (mặc định an toàn hơn). • true - Chuyển tiếp tiêu đề Bearer <token> đến máy chủ MCP phía trên. • Bật nếu máy chủ MCP của bạn cần đọc token (ví dụ: để trích xuất danh tính người dùng hoặc các yêu cầu). |

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| Enable ACL | boolean | Không | false | false - Bất kỳ token hợp lệ nào cũng cấp quyền truy cập vào tất cả các phương thức MCP (vẫn thực hiện xác thực token). true - Sau khi xác thực token, plugin cũng kiểm tra các phạm vi/nhóm của token so với Scope Method Mapping để quyết định xem phương thức JSON-RPC cụ thể có được phép hay không. |
| ACL Claim | string | Không | phạm vi | • Tên của yêu cầu JWT chứa quyền của người dùng. Plugin đọc yêu cầu này và sử dụng các giá trị của nó cho các kiểm tra ACL. • Các giá trị phổ biến: → mcp_scopes - Yêu cầu tùy chỉnh từ Keycloak Protocol Mapper ⚠️ Phải exactly match tên yêu cầu Token trong Keycloak Protocol Mapper. |
Bản đồ mỗi phạm vi/nhóm đến một danh sách các phương thức MCP JSON-RPC mà phạm vi đó được phép gọi. Chỉ có hiệu lực khi Enable ACL là true

| Field | Type | Required | Description |
|---|---|---|---|
| Scope | string | Yes (per entry) | Tên phạm vi/vai trò. Phải khớp với một giá trị xuất hiện trong yêu cầu JWT được chỉ định bởi ACL Claim. Example: mcp:tools |
| Methods | array of strings | Yes (per entry) | Tên phương thức MCP JSON-RPC mà phạm vi này được phép gọi. Nhập từng tên phương thức và nhấn Enter để thêm. Example: tools/list, tools/call |
⚠️ When ACL is enabled but Scope Method Mapping is empty: Tất cả các yêu cầu đều bị từ chối. Bạn phải cấu hình ít nhất một ánh xạ.
💡 Permissions are additive: Một người dùng chỉ cần MỘT phạm vi cho phép phương thức. Nếu bất kỳ phạm vi nào trong token cho phép phương thức, quyền truy cập sẽ được cấp.
Section 7: TIMEOUTS & CACHING| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| Token Cache TTL (s) | number | No | 300 | Thời gian (tính bằng giây) mà một token đã được xác thực được lưu trong bộ nhớ chia sẻ của Kong. Trong khoảng thời gian này, các yêu cầu lặp lại với cùng một token sẽ bỏ qua việc giải mã JWT và xác minh chữ ký. Ngay cả khi đã được lưu, plugin sẽ kiểm tra lại yêu cầu JWT exp trên mỗi yêu cầu và vô hiệu hóa các token đã hết hạn. |
| HTTP Timeout (ms) | number | No | 10000 | Thời gian chờ (tính bằng mili giây) cho các yêu cầu HTTP để lấy JWKS (khóa ký công khai) từ máy chủ ủy quyền. Nếu máy chủ auth không phản hồi trong khoảng thời gian này, việc xác thực token sẽ thất bại. • Tăng nếu máy chủ auth đang ở trên một mạng chậm hoặc khởi động lạnh • Giảm để thất bại nhanh hơn khi máy chủ auth không thể truy cập |
3. Cài đặt Keycloak
3.1. Nền tảng Keycloak OAuth2
Các bước này cấu hình Keycloak để các khách hàng MCP có thể phát hiện máy chủ ủy quyền và nhận token với đối tượng chính xác.
3.1.1 Tạo phạm vi khách hàng
What this does: Tạo một phạm vi có tên mà khách hàng có thể yêu cầu. Khi một khách hàng yêu cầu phạm vi, Keycloak sẽ bao gồm nó trong token - và bất kỳ bộ ánh xạ nào gắn liền với phạm vi này cũng sẽ được kích hoạt.
Step 1: Navigate to Keycloak Admin → Client scopes → Create client scope

| Field | Value | Why |
|---|---|---|
| Name | mcp:tools | Tên phạm vi mà khách hàng MCP của bạn sẽ yêu cầu |
| Protocol | OpenID Connect | Giao thức OAuth2/OIDC tiêu chuẩn |
| Display on consent screen | ON | Hiển thị những gì khách hàng đang yêu cầu trong quá trình đăng nhập |
| Consent screen text | Truy cập công cụ MCP | Mô tả dễ hiểu cho người dùng |
| Include in token scope | ON | Đảm bảo giá trị phạm vi xuất hiện trong yêu cầu JWT scope |
3.1.2 Thêm Bộ Ánh Xạ Đối Tượng
What this does: Thêm một yêu cầu aud (đối tượng) vào token truy cập. Plugin xác thực rằng đối tượng của token khớp với giá trị đã cấu hình của nó - điều này ngăn chặn các token được phát hành cho các dịch vụ other không được chấp nhận bởi điểm cuối MCP của bạn.
Step 1: Navigate to The mcp:tools scope you just created → Mappers tab → Configure a new mapper → Select Audience

| Field | Value | Why |
|---|---|---|
| Name | audience-config | Tên mô tả cho bộ ánh xạ này |
| Included Custom Audience | audience-name | Phải khớp với trường đối tượng trong cấu hình plugin Kong |
| Add to access token | BẬT | Plugin đọc mã thông báo truy cập, không phải mã thông báo ID |
| Add to ID token | TẮT | Mã thông báo ID dành cho ứng dụng khách, không phải máy chủ tài nguyên |
![]() |
3.1.3. Tạo Client mới
What this does: Tạo một client cho client MCP để kết nối với Keycloak.
Step 1: Navigate to Clients → Create client

| Field | Value | Description |
|---|---|---|
| Client ID | Mcp-client | Client ID |


3.2. Keycloak: Thiết lập ACL dựa trên Nhóm
Phần này thiết lập fine-grained access control để các người dùng khác nhau nhận được các quyền MCP khác nhau. Kiến trúc là:
Nhóm → Vai trò Realm → Bộ lập bản đồ Giao thức → "mcp_scopes" yêu cầu JWT → ACL
3.2.1. Tạo Vai trò Realm
What these are: Các cấp độ quyền được đặt tên. Mỗi vai trò đại diện cho một tập hợp các phương thức MCP mà người dùng được phép gọi. Tên vai trò sẽ xuất hiện trong yêu cầu JWT mcp_scopes.
Step 1: Navigate to: Realm roles → Create role (repeat for each)
| Role Name | Purpose | Example MCP Methods |
|---|---|---|
| mcp:tools | Để truy cập công cụ | tools/list |
| mcp:resources | Để truy cập tài nguyên | resources/read |
![]() |
3.2.2. Tạo Nhóm
What these are: Các container tổ chức cho người dùng. Thay vì gán vai trò cho từng người dùng, bạn gán vai trò cho một nhóm và sau đó thêm người dùng vào nhóm.
Step 1: Navigate to: Groups → Create group

| Group Name | Description |
|---|---|
| mcp-member | Quyền truy cập thành viên cơ bản |
| mcp-admin | Quyền truy cập đầy đủ vào tất cả các công cụ, tài nguyên MCP |
![]() |
3.2.3. Gán Vai Trò cho Nhóm
Step 1: Navigate to Groups → Click a group → Role mapping tab → Assign role| Group | Roles to Assign |
|---|---|
| Mcp-admin | mcp:tools, mcp:resources |
| Mcp-member | mcp:tools |
![]() |
Nhấp vào Assign

3.2.4. Tạo Bộ ánh xạ giao thức (mcp_scopes Claim)
What this does: Yêu cầu Keycloak bao gồm các vai trò miền của người dùng (được lọc bởi tiền tố mcp:) như một claim tùy chỉnh gọi là mcp_scopes trong token truy cập. Đây là claim mà plugin Kong đọc để đưa ra quyết định ACL. Step 4: Navigate to Client scopes → mcp:tools → Mappers tab → Add mapper → By configuration → Select User Realm Role



| Field | Value | Why |
|---|---|---|
| Name | mcp-scopes-mapper | Tên mô tả |
| Mapper Type | Vai trò miền người dùng | Ánh xạ các vai trò miền của người dùng tới một yêu cầu token |
| Token Claim Name | mcp_scopes | Phải khớp với acl_claim trong cấu hình plugin Kong |
| Multivalued | BẬT | Người dùng có thể có nhiều vai trò |
| Add to access token | BẬT | Plugin đọc token truy cập |
| Add to ID token | TẮT | Không cần thiết cho xác thực máy chủ tài nguyên |
| Add to userinfo | TẮT | Không cần thiết |
Critical: Mục Token Claim Name (mcp_scopes) phải exactly match trường acl_claim trong cấu hình plugin Kong. Một sự không khớp có nghĩa là plugin không thể tìm thấy các quyền trong token.
3.2.5. Thêm người dùng vào nhóm
Step 1: Navigate to Users → Click on a user → Groups tab → Join group → Select the appropriate group
| User | Group | Resulting JWT mcp_scopes |
|---|---|---|
| canhng1 | Mcp-member | Mcp:tools, Mcp:resources |
| admin | mcp-admin | Mcp:resources |
![]() |
4. Kiểm tra bằng Visual Studio Code
4.1. Chuyển tiếp proxy Kong đến địa phương

4.2. Tạo máy chủ MCP mới
Mở Vs Code, nhấn Ctrl + Shift + P và chọn MCP: Add server…. Chọn HTTP và nhập http://localhost:8100. Đặt cho máy chủ một tên duy nhất để sử dụng trong Visual Studio Code. Trong mcp.json bạn sẽ thấy một mục như thế này:


4.3. Khởi động máy chủ và kết nối đến máy chủ MCP giả lập với xác thực Keyloak





Đăng nhập thành công và kết nối đến máy chủ MCP giả lập với 22 công cụ.




