feat(router): support multiple OAuth authorization servers for MCP - #3148
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughChangesThe router now supports multiple MCP OAuth authorization servers. It merges legacy and plural configuration, advertises all configured servers, validates tokens from configured issuers, and rejects tokens from unknown issuers. Documentation and tests cover the new configuration. ChangesMultiple OAuth authorization servers
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Comment |
Router image scan passed✅ No security vulnerabilities found in image: |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3148 +/- ##
==========================================
+ Coverage 62.40% 62.53% +0.13%
==========================================
Files 263 263
Lines 31048 31060 +12
==========================================
+ Hits 19375 19424 +49
+ Misses 10163 10119 -44
- Partials 1510 1517 +7
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
router/pkg/config/config_test.go (1)
2506-2532: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTest empty authorization server URLs.
AuthorizationServersremoves empty entries. This table does not verify that contract. Add a case with empty values around valid URLs.Proposed test case
+ { + name: "empty urls are removed", + config: MCPOAuthConfiguration{ + AuthorizationServerURLs: []string{"", "https://auth-a.example.com", ""}, + }, + expected: []string{"https://auth-a.example.com"}, + },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@router/pkg/config/config_test.go` around lines 2506 - 2532, Extend the AuthorizationServers table-driven tests with a case containing empty authorization server URL values before, between, or after valid URLs. Set the expected result to include only the valid URLs in their preserved order, verifying that AuthorizationServers removes empty entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@router-tests/protocol/mcp_oauth_e2e_test.go`:
- Around line 268-279: Update the “rejects tokens from an unknown authorization
server” test to create and sign the token with configured oauthServerA or
oauthServerB, then override its iss claim with oauthServerUnknown.Issuer(). Keep
the connection and unauthorized AuthError assertions unchanged so the test
isolates issuer validation rather than JWKS or signature failure.
---
Nitpick comments:
In `@router/pkg/config/config_test.go`:
- Around line 2506-2532: Extend the AuthorizationServers table-driven tests with
a case containing empty authorization server URL values before, between, or
after valid URLs. Set the expected result to include only the valid URLs in
their preserved order, verifying that AuthorizationServers removes empty
entries.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 89f0fa7f-9892-4581-aa09-49f7c56d154e
📒 Files selected for processing (11)
docs-website/router/mcp/oauth/configuration.mdxdocs-website/router/mcp/oauth/quickstart.mdxrouter-tests/protocol/mcp_oauth_e2e_test.gorouter-tests/testutil/oauth_server.gorouter/pkg/config/config.gorouter/pkg/config/config.schema.jsonrouter/pkg/config/config_test.gorouter/pkg/config/testdata/config_defaults.jsonrouter/pkg/config/testdata/config_full.jsonrouter/pkg/mcpserver/protected_resource_metadata_test.gorouter/pkg/mcpserver/server.go
…f authorization_server_urls
There was a problem hiding this comment.
Claude Code Review
Claude Code Review is paused for this repository. To reconnect it, an admin of this repository's GitHub organization (or the account owner, for personal repositories) who can also manage your Claude organization's Code Review settings needs to re-link GitHub in Code Review settings. This is a one-time step.
Tip: disable this comment in your organization's Code Review settings.
…authorization-servers-for-mcp
…authorization-servers-for-mcp
…tiple-oauth-authorization-servers-for-mcp' into ahmet/router-613-mcp-support-multiple-oauth-authorization-servers-for-mcp
There was a problem hiding this comment.
Claude Code Review
Claude Code Review is paused for this repository. To reconnect it, an admin of this repository's GitHub organization (or the account owner, for personal repositories) who can also manage your Claude organization's Code Review settings needs to re-link GitHub in Code Review settings. This is a one-time step.
Tip: disable this comment in your organization's Code Review settings.
…authorization-servers-for-mcp
Summary by CodeRabbit
New Features
Documentation
Tests
Problem
The router MCP server supports OAuth authentication. The config option
mcp.oauth.authorization_server_urlaccepts one authorization server URL. The router advertises this one URL to MCP clients through the RFC 9728 Protected Resource Metadata endpoint. Platform teams with more than one identity provider cannot advertise all of them.Closes ROUTER-613.
Solution
This PR adds the config option
mcp.oauth.authorization_server_urls. The option accepts a list of authorization server URLs. The router advertises all configured servers in the metadata endpoint. MCP clients select one of the advertised servers for authorization.The new option supersedes
authorization_server_url. This PR deprecates the old option. The old option continues to work. See "Backward compatibility" below.The environment variable
MCP_OAUTH_AUTHORIZATION_SERVER_URLSsets the same option. It accepts a comma-separated list.Token validation logic is unchanged. The router validates each token against every configured
jwksprovider. This mechanism already supports multiple issuers. Configure onejwksentry for each authorization server.Changes
router/pkg/config: Add the fieldAuthorizationServerURLstoMCPOAuthConfiguration. Add the methodAuthorizationServers(). The method merges the single URL and the list. The single URL comes first. The method removes duplicate and empty entries.router/pkg/config: Deprecateauthorization_server_url. The schema marks the option as deprecated. The Go field carries a// Deprecated:comment.router/pkg/mcpserver: The metadata response, the metadata endpoint registration check, and the startup log now use the merged list.router/pkg/config/config.schema.json: Add the schema entry for the new option.docs-website/router/mcp/oauth/configuration.mdx: Add a "Multiple Authorization Servers" section with an example config. Add the new option to the option table and the environment variable table. Mark the old option as deprecated.docs-website/router/mcp/oauth/quickstart.mdx: Config examples useauthorization_server_urls.Backward compatibility
The option
authorization_server_urlis deprecated but works unchanged. Deprecation is a signal, not a removal. You can set both options together. The router merges them into one list. Editors that use the config schema show a deprecation hint.Tests
test_rsa.Notes for reviewers
JWKS key lookup matches the token
kidper provider. Two issuers with the samekidand different keys can still fail validation. This limitation exists before this PR (see ROUTER-143). Identity providers use distinct key IDs in practice.Checklist