-
Notifications
You must be signed in to change notification settings - Fork 232
feat: Support MCP Authn when configured by xDS #637
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
howardjohn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG!
| return Self::create_auth_required_response(&req, auth).into_response(); | ||
| }, | ||
| // if no mcp authn is configured or JWT already validated (claims exist), do nothing | ||
| _ => {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm... so in theory now I can have 3 JWT policies: Gateway Route and MCPBackend.
The first 2 do not have this "allow if previous already did it". Maybe it should given its impossible for it to pass if you have multiple, given we strip the token. But maybe we need to be consistent across all 3?
I am a bit worried about silently ignoring the auth though....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's definitely a fair point.
I'm okay with changing the MCP authn behavior to reject in cases where the token was stripped earlier on if we think multiple JWT policy configuration is a complete anti-pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just made the update to follow the behavior of the first 2 for the time being. We can always come back and address the other cases as a follow up later if there is demand.
007ff15 to
3e68606
Compare
|
Confirmed it works with kgateway xds + keycloak! 🎉 kgateway-dev/kgateway#12928 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for MCP authentication when configured via xDS (dynamic configuration). Previously, MCP authentication only worked with local configuration using route-level JWT policies. The new implementation performs JWT validation directly in the MCP backend policy, allowing the control plane to provide JWKS inline rather than requiring dynamic JWKS fetching.
Key changes:
- Changed
audience(singular) toaudiences(array) andjwksUrltojwks(supporting inline/file/URL) in the MCP authentication schema - Added inline JWT validation in the MCP router for xDS-configured backends, bypassing the normal backend policy flow
- Modified the proto definition to use
jwks_inlineandaudiencesfields, with resource metadata now usingmap<string, string>instead ofmap<string, google.protobuf.Value>
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| schema/local.json | Updated JSON schema to support audiences array and jwks object with file/url/inline options |
| schema/README.md | Updated documentation to reflect the new schema field names |
| go/api/resource.pb.go | Generated protobuf code reflecting proto changes to audiences and jwks_inline fields |
| examples/mcp-authentication/config.yaml | Migrated example configs from audience/jwksUrl to audiences/jwks.url |
| crates/agentgateway/src/types/agent_xds.rs | Added xDS conversion logic to parse inline JWKS and create JWT validators |
| crates/agentgateway/src/types/agent.rs | Updated McpAuthentication struct with audiences array, jwks field, and jwt_validator |
| crates/agentgateway/src/mcp/router.rs | Implemented JWT validation logic directly in router for MCP backends |
| crates/agentgateway/proto/resource.proto | Changed proto fields from audience/jwks_url to audiences/jwks_inline and simplified resource metadata |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let val = serde_json::from_str::<serde_json::Value>(v) | ||
| .unwrap_or(serde_json::Value::String(v.clone())); |
Copilot
AI
Nov 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error from serde_json::from_str is silently ignored. Consider logging the parse error to help diagnose configuration issues when the control plane provides malformed JSON values in resource metadata.
Signed-off-by: npolshakova <nina.polshakova@solo.io>
c3540a1 to
8c5e059
Compare
Signed-off-by: npolshakova <nina.polshakova@solo.io>
Currently, agentgateway only supports MCP authentication configured locally.
Under the hood, local config creates a route-level JWT policy for MCP authentication. We can't take this same approach when configured via xDS, since config arrives dynamically and expecting the control plane to configure route-level policies for all routes that reference an MCP backend would be quite complex in practice.
Instead, I've implemented JWT validation for MCP authentication similar to how backend policies work. MCP Authentication now includes JWT verification directly, which avoids the introduction of a backend JWT policy that only works with MCP backends.
I've also updated the MCP authentication proto/xds code to expect inline JWKS, since we expect the control plane to handle JWKS fetch.
Since MCP backends seem to bypass the normal apply_backend_policies flow (they return early in make_backend_call), JWT validation is currently applied directly in the MCP router.