Skip to content

Commit 658af29

Browse files
authored
Merge pull request #109672 from ShaunaDiaz/OSDOCS-17718
OSDOCS-17718: adds authentication to MCP gateway docs
2 parents cab138f + 3436cae commit 658af29

5 files changed

Lines changed: 231 additions & 10 deletions

File tree

_topic_maps/_topic_map.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ Topics:
7979
File: mcp-gateway-register-ext-mcp-servers
8080
- Name: Configuring authentication for the MCP gateway
8181
File: mcp-gateway-authz
82-
- Name: Configuring authorization for the MCP gateway
83-
File: mcp-gateway-authn
82+
- Name: Configuring authentication for the MCP gateway
83+
File: mcp-gateway-authentication
8484
- Name: Using credentials to access external APIs
8585
File: mcp-gateway-vault
8686
---
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
:_mod-docs-content-type: ASSEMBLY
2+
include::_attributes/attributes.adoc[]
3+
[id="mcp-gateway-authentication"]
4+
= Using authentication with {mcpg}
5+
:context: mcp-gateway-authentication
6+
7+
[role="_abstract"]
8+
You can configure authentication for {mcpg} by using an `AuthPolicy` custom resource (CR) with an identity provider, or any Istio or Gateway API compatible mechanism.
9+
10+
include::modules/con-mcp-gateway-authentication.adoc[leveloffset=+1]
11+
12+
include::modules/proc-configure-mcp-gateway-authentication.adoc[leveloffset=+1]

mcp_gateway_config/mcp-gateway-authn.adoc

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
// Module included in the following assemblies:
3+
//
4+
// *mcp_gateway_config/mcp-gateway-authentication.adoc
5+
6+
:_mod-docs-content-type: CONCEPT
7+
[id="con-mcp-gateway-authentication_{context}"]
8+
= Understanding {mcpg} authentication
9+
10+
[role="_abstract"]
11+
When you enable authentication, the {mcpg} broker component exposes OAuth 2.0 Protected Resource Metadata, enabling MCP clients to discover your authorization server and complete the authentication flow.
12+
13+
You can implement the following actions by using authentication:
14+
15+
* Set up the {mcpg} to validate access tokens issued by your identity provider.
16+
* Return a `401` error message with authorization server discovery information.
17+
* Expose OAuth configuration at `/.well-known/oauth-protected-resource`.
18+
* Enable MCP clients to discover and use your identity provider's client registration.
19+
20+
The following procedure uses a Kuadrant `AuthPolicy` with {keycloak} as an identity provider example. The {mcpg} supports any Istio or Gateway API compatible authentication mechanism.
21+
22+
[role="_additional-resources"]
23+
.Additional resources
24+
25+
* link:https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization[MCP Authorization specification]
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
// Module included in the following assemblies:
2+
//
3+
// *mcp_gateway_config/mcp-gateway-authentication.adoc
4+
5+
:_mod-docs-content-type: PROCEDURE
6+
[id="proc-configure-mcp-gateway-authentication_{context}"]
7+
= Configuring {mcpg} authentication with an AuthPolicy
8+
9+
[role="_abstract"]
10+
Configure authentication for your {mcpg} by using a Kuadrant `AuthPolicy` custom resource (CR) and an identity provider such as {keycloak}.
11+
12+
[NOTE]
13+
====
14+
The {mcpg} supports any Istio or Gateway API compatible authentication mechanism. Use the best solution for your {ocp} clusters.
15+
====
16+
17+
.Prerequisites
18+
19+
* You installed {mcpg}.
20+
* You installed {prodname}.
21+
* You configured a `Gateway` object.
22+
* You installed and have ready an identity provider supporting OAuth 2.0 or 2.1, for example, {keycloak}.
23+
24+
.Procedure
25+
26+
. Add a listener to the `Gateway` object for your identity provider by using the following command as an example:
27+
+
28+
[source,json,subs="+quotes"]
29+
----
30+
$ oc patch gateway _<mcp_gateway>_ -n _<gateway_system>_ --type json -p '[
31+
{
32+
"op": "add",
33+
"path": "/spec/listeners/-",
34+
"value": {
35+
"name": "keycloak",
36+
"hostname": "keycloak.example.com",
37+
"port": 8002,
38+
"protocol": "HTTP",
39+
"allowedRoutes": {
40+
"namespaces": {
41+
"from": "Selector",
42+
"selector": {
43+
"matchLabels": {
44+
"kubernetes.io/metadata.name": "keycloak"
45+
}
46+
}
47+
}
48+
}
49+
}
50+
}
51+
]'
52+
----
53+
+
54+
* Replace `_<mcp_gateway>_` with the name of your MCP gateway.
55+
* Replace `_<gateway_system>_` with the namespace of your `Gateway` object.
56+
* Replace the {keycloak} `_<name>_`, `_<hostname>_`, and `_<kubernetes.io/metadata.name>_` with your identity provider information.
57+
58+
. Configure the {mcpg} broker component to respond with OAuth discovery information by setting the following environment variables:
59+
+
60+
[source,terminal,subs="+quotes"]
61+
----
62+
$ oc set env deployment/_<mcp_gateway>_ \
63+
OAUTH_RESOURCE_NAME="MCP Server" \
64+
OAUTH_RESOURCE="http://mcp.example.com:8001/mcp" \
65+
OAUTH_AUTHORIZATION_SERVERS="http://keycloak.example.com:8002/realms/mcp" \
66+
OAUTH_BEARER_METHODS_SUPPORTED="header" \
67+
OAUTH_SCOPES_SUPPORTED="basic,groups,roles,profile" \
68+
-n _<mcp_system>_
69+
----
70+
+
71+
* Replace `_<mcp_gateway>_` with the name of your MCP gateway.
72+
* Replace `_<mcp_system>_` with the namespace of your MCP gateway.
73+
* `OAUTH_RESOURCE_NAME`: Human-readable name for the MCP server.
74+
* `OAUTH_RESOURCE`: Canonical URI of the MCP server that is used for token audience validation.
75+
* `OAUTH_AUTHORIZATION_SERVERS`: Authorization server URL for client discovery.
76+
* `OAUTH_BEARER_METHODS_SUPPORTED`: Supported bearer token methods. Valid values are usually `header`, `body`, or `query`.
77+
* `OAUTH_SCOPES_SUPPORTED`: The OAuth scopes this MCP server supports.
78+
79+
. Create an AuthPolicy CR that validates JWT tokens:
80+
+
81+
.Example AuthPolicy CR
82+
[source,yaml,subs="+quotes"]
83+
----
84+
apiVersion: kuadrant.io/v1
85+
kind: AuthPolicy
86+
metadata:
87+
name: _<mcp_jwt_auth_policy>_
88+
namespace: _<gateway_system>_
89+
spec:
90+
targetRef:
91+
group: gateway.networking.k8s.io
92+
kind: Gateway
93+
name: _<mcp_gateway>_
94+
sectionName: _<mcp>_
95+
defaults:
96+
when:
97+
- predicate: "!request.path.contains('/.well-known')"
98+
rules:
99+
authentication:
100+
'keycloak':
101+
jwt:
102+
issuerUrl: http://keycloak.example.com:8002/realms/mcp
103+
response:
104+
unauthenticated:
105+
code: 401
106+
headers:
107+
'WWW-Authenticate':
108+
value: Bearer resource_metadata=http://mcp.example.com:8001/.well-known/oauth-protected-resource/mcp
109+
body:
110+
value: |
111+
{
112+
"error": "Unauthorized",
113+
"message": "Authentication required."
114+
}
115+
----
116+
+
117+
* The `metadata.name:` parameter value is the name of the `AuthPolicy` CR. Replace `_<mcp_jwt_auth_policy>_` as needed.
118+
* The `metadata.namespace:` parameter value is the gateway namespace. Replace `_<gateway_system>_` with the namespace where you created your `Gateway` object to apply the `AuthPolicy` CR to the namespace.
119+
* The `spec.targetRef.name:` parameter value is the name of your MCP gateway. Replace `_<mcp_gateway>_` as needed.
120+
* The `spec.targetRef.sectionName:` parameter value is the target gateway listener. In this example, `mcp` is used.
121+
* The `spec.defaults.when` parameter value in this example allows unauthenticated access to `/.well-known` endpoints.
122+
* The `spec.defaults.rules.authentication:` parameter defines which tokens to validate and how. In this case, JWT validation validates tokens against Keycloak's OIDC issuer.
123+
* The `spec.defaults.rules.response.unauthenticated.headers.'WWW-Authenticate':` parameter points clients to OAuth discovery metadata. Replace the `resource_metadata=` information as required.
124+
* The `spec.defaults.rules.response.unauthenticated.body.value:` parameter is set with a standard response. This configuration returns a `401` error in an OAuth error format.
125+
126+
. Apply the AuthPolicy CR by running the following command:
127+
+
128+
[source,terminal,subs="+quotes"]
129+
----
130+
$ oc apply -f _<mcp_jwt_authpolicy.yaml>_
131+
----
132+
+
133+
Replace `_<mcp_jwt_authpolicy.yaml>_` with the name of your CR.
134+
135+
.Verification
136+
137+
. Test that the broker now serves OAuth discovery information by checking the protected resource metadata endpoint with the following command:
138+
+
139+
[source,terminal,subs="+quotes"]
140+
----
141+
$ curl http://_<mcp.example.com:8001/.well_known/oauth_protected_resource>_
142+
----
143+
+
144+
* Replace the URL with your protected resource information.
145+
+
146+
.Example output
147+
[source,text]
148+
----
149+
{
150+
"resource_name": "MCP Server",
151+
"resource": "http://example.com:8001/mcp",
152+
"authorization_servers": [
153+
"http://keycloak.example.com:8002/realms/mcp"
154+
],
155+
"bearer_methods_supported": [
156+
"header"
157+
],
158+
"scopes_supported": [
159+
"basic",
160+
"groups",
161+
"roles",
162+
"profile"
163+
]
164+
}
165+
----
166+
167+
. Test that protected endpoints now require authentication by running the following command:
168+
+
169+
[source,terminal,subs="+quotes"]
170+
----
171+
$ curl -v http://_<mcp.example.com:8001/mcp>_ \
172+
-H "Content-Type: application/json" \
173+
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'
174+
----
175+
+
176+
Replace `_<mcp.example.com:8001/mcp>_` with your endpoint.
177+
+
178+
.Example output
179+
[source,text]
180+
----
181+
{
182+
"error": "Unauthorized",
183+
"message": "Authentication required."
184+
}
185+
----
186+
+
187+
A `401` error with `WWW-Authenticate` header is expected.
188+
189+
.Next steps
190+
191+
* Control which users can access specific tools by configuring authorization policies.
192+
* Connect authenticated external MCP services.

0 commit comments

Comments
 (0)