Skip to content

Commit a2f2b99

Browse files
authored
Merge pull request #704 from RakhithaRR/mcp-authz
Add MCP Authorization policy
2 parents 550787a + 58ded66 commit a2f2b99

File tree

10 files changed

+1416
-16
lines changed

10 files changed

+1416
-16
lines changed
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
# MCP Authorization
2+
3+
## Overview
4+
5+
The MCP Authorization policy provides fine-grained access control for Model Context Protocol (MCP) server resources. It enables API administrators to define authorization rules based on user claims and scopes extracted from validated JWT tokens, controlling access to specific MCP tools, resources, prompts, and JSON-RPC methods.
6+
7+
> **Prerequisite**: The MCP Authorization policy requires the [MCP Authentication policy](./mcp-authentication.md) to be applied first. The MCP Authentication policy validates and extracts JWT claims that are used by the authorization policy for access control decisions.
8+
9+
## Features
10+
11+
- **Tool-Level Access Control**: Restrict access to specific MCP tools based on user claims and scopes
12+
- **Resource-Level Access Control**: Control access to specific MCP resources based on authorization rules
13+
- **Prompt-Level Access Control**: Manage access to specific MCP prompts
14+
- **JSON-RPC Method-Level Access Control**: Apply authorization rules at the JSON-RPC method level (e.g., `tools/call`, `resources/read`, `prompts/get`) for fine-grained control. Only methods under `tools/`, `resources/`, and `prompts/` are evaluated.
15+
- **Flexible Rule-Based Authorization**: Define multiple authorization rules with attribute matching (exact or wildcard)
16+
- **Claim-Based Validation**: Validate custom claims (e.g., department, role, team) in user tokens
17+
- **Scope-Based Validation**: Require specific OAuth scopes for accessing protected resources
18+
- **Wildcard Matching**: Use wildcard patterns ("*") to create default rules for all resources of a type
19+
20+
## Configuration
21+
22+
The MCP Authorization policy uses a single-level configuration model where all parameters are configured per-MCP-API/route in the API definition YAML.
23+
24+
### User Parameters (API Definition)
25+
26+
These parameters are configured per MCP Proxy by the API developer:
27+
28+
| Parameter | Type | Required | Default | Description |
29+
|-----------|------|----------|---------|-------------|
30+
| `rules` | array | Yes | - | List of authorization rules that define access control policies for MCP resources. |
31+
| `rules[].attribute` | object | Yes | - | The MCP resource attribute to which the authorization rule applies. |
32+
| `rules[].attribute.type` | string | Yes | - | Type of MCP resource: "tool", "resource", "prompt", "method". |
33+
| `rules[].attribute.name` | string | No | - | Name or identifier of the resource. Use "*" for wildcard matching (applies to all resources of the specified type). Examples: "list_files" for tools, "file:///some_resource" for resources, "weather_summary" for prompts, "tools/call" for methods. |
34+
| `rules[].requiredScopes` | array | No | - | List of OAuth scopes required to access this resource. The token must contain all of the specified scopes. |
35+
| `rules[].requiredClaims` | object | No | - | Map of claim names to expected values. All specified claims must be present in the token with matching values. |
36+
37+
## MCP Proxy Definition Examples
38+
39+
### Example 1: Basic Tool Access Control
40+
41+
Restrict access to specific tools based on scopes:
42+
43+
```yaml
44+
apiVersion: gateway.api-platform.wso2.com/v1alpha1
45+
kind: Mcp
46+
metadata:
47+
name: mcp-server-api-v1.0
48+
spec:
49+
displayName: mcp-server-api
50+
version: v1.0
51+
context: /mcpserver
52+
vhost: mcp1.gw.example.com
53+
upstream:
54+
url: https://mcp-backend:8080
55+
policies:
56+
- name: mcp-auth
57+
version: v0.1.0
58+
params:
59+
issuers:
60+
- PrimaryIDP
61+
- name: mcp-authz
62+
version: v0.1.0
63+
params:
64+
rules:
65+
- attribute:
66+
type: tool
67+
name: list_files
68+
requiredScopes:
69+
- mcp:tool:read
70+
- attribute:
71+
type: tool
72+
name: create_file
73+
requiredScopes:
74+
- mcp:tool:write
75+
- attribute:
76+
type: tool
77+
name: "*"
78+
requiredScopes:
79+
- mcp:tool:execute
80+
tools:
81+
...
82+
```
83+
84+
### Example 2: Claim-Based Resource Access
85+
86+
Control resource access based on user claims:
87+
88+
```yaml
89+
apiVersion: gateway.api-platform.wso2.com/v1alpha1
90+
kind: Mcp
91+
metadata:
92+
name: mcp-server-api-v1.0
93+
spec:
94+
displayName: mcp-server-api
95+
version: v1.0
96+
context: /mcpserver
97+
vhost: mcp1.gw.example.com
98+
upstream:
99+
url: https://mcp-backend:8080
100+
policies:
101+
- name: mcp-auth
102+
version: v0.1.0
103+
params:
104+
issuers:
105+
- PrimaryIDP
106+
- name: mcp-authz
107+
version: v0.1.0
108+
params:
109+
rules:
110+
- attribute:
111+
type: resource
112+
name: "file:///private/main"
113+
requiredClaims:
114+
department: "engineering"
115+
requiredScopes:
116+
- mcp:resource:read
117+
- attribute:
118+
type: resource
119+
name: "file:///public/main"
120+
requiredScopes:
121+
- mcp:resource:read
122+
tools:
123+
...
124+
```
125+
126+
### Example 3: Role-Based Prompt Access
127+
128+
Restrict prompt access based on user roles:
129+
130+
```yaml
131+
apiVersion: gateway.api-platform.wso2.com/v1alpha1
132+
kind: Mcp
133+
metadata:
134+
name: mcp-server-api-v1.0
135+
spec:
136+
displayName: mcp-server-api
137+
version: v1.0
138+
context: /mcpserver
139+
vhost: mcp1.gw.example.com
140+
upstream:
141+
url: https://mcp-backend:8080
142+
policies:
143+
- name: mcp-auth
144+
version: v0.1.0
145+
params:
146+
issuers:
147+
- PrimaryIDP
148+
- name: mcp-authz
149+
version: v0.1.0
150+
params:
151+
rules:
152+
- attribute:
153+
type: prompt
154+
name: "admin_summary"
155+
requiredClaims:
156+
role: "admin"
157+
requiredScopes:
158+
- mcp:prompt:admin
159+
- attribute:
160+
type: prompt
161+
name: "*"
162+
requiredScopes:
163+
- mcp:prompt:read
164+
tools:
165+
...
166+
```
167+
168+
### Example 4: Multi-Level Authorization
169+
170+
Combine different resource types with varying access requirements:
171+
172+
```yaml
173+
apiVersion: gateway.api-platform.wso2.com/v1alpha1
174+
kind: Mcp
175+
metadata:
176+
name: mcp-server-api-v1.0
177+
spec:
178+
displayName: mcp-server-api
179+
version: v1.0
180+
context: /mcpserver
181+
vhost: mcp1.gw.example.com
182+
upstream:
183+
url: https://mcp-backend:8080
184+
policies:
185+
- name: mcp-auth
186+
version: v0.1.0
187+
params:
188+
issuers:
189+
- PrimaryIDP
190+
requiredScopes:
191+
- mcp:access
192+
- name: mcp-authz
193+
version: v0.1.0
194+
params:
195+
rules:
196+
# Restrictive tool access
197+
- attribute:
198+
type: tool
199+
name: "execute_command"
200+
requiredClaims:
201+
department: "platform"
202+
role: "admin"
203+
requiredScopes:
204+
- mcp:tool:execute:admin
205+
# General tool access
206+
- attribute:
207+
type: tool
208+
name: "*"
209+
requiredScopes:
210+
- mcp:tool:execute
211+
# Resource access for finance department
212+
- attribute:
213+
type: resource
214+
name: "file:///finance/*"
215+
requiredClaims:
216+
department: "finance"
217+
requiredScopes:
218+
- mcp:resource:read:finance
219+
# Public resources
220+
- attribute:
221+
type: resource
222+
name: "*"
223+
requiredScopes:
224+
- mcp:resource:read
225+
tools:
226+
...
227+
```
228+
229+
## Authorization Decision Examples
230+
231+
**Scenario 1**: User with scope `mcp:tool:read` attempts to call `list_files` tool
232+
- Rule: `attribute.type="tool", attribute.name="list_files", requiredScopes=["mcp:tool:read"]`
233+
- Result: ✅ Access Granted
234+
235+
**Scenario 2**: User with scope `mcp:tool:execute` (no write scope) attempts to call `create_file` tool
236+
- Rule: `attribute.type="tool", attribute.name="create_file", requiredScopes=["mcp:tool:write"]`
237+
- Result: ❌ Access Denied (insufficient scopes)
238+
239+
**Scenario 3**: User with claim `department="engineering"` attempts to read resource `file:///private/code`
240+
- Rule: `attribute.type="resource", attribute.name="file:///private/code", requiredClaims={department="engineering"}`
241+
- Result: ✅ Access Granted
242+
243+
**Scenario 4**: User with claim `department="finance"` (no engineering) attempts to read resource `file:///private/code`
244+
- Rule: `attribute.type="resource", attribute.name="file:///private/code", requiredClaims={department="engineering"}`
245+
- Result: ❌ Access Denied (claim mismatch)
246+
247+
## Error Handling
248+
249+
When authorization fails, the policy returns:
250+
- **HTTP Status**: `403 Forbidden`
251+
- **Response Body**: JSON error response with a reason message
252+
- **WWW-Authenticate Header**: Contains information about required scopes for the denied resource
253+
254+
## Related Policies
255+
256+
- [MCP Authentication Policy](./mcp-authentication.md) - Validates JWT tokens and is a prerequisite for MCP Authorization
257+
- [JWT Authentication Policy](../../../gateway/policies/jwt-authentication.md) - Base JWT token validation mechanism

0 commit comments

Comments
 (0)