Skip to content

fix(auth-router): correct Protected Resource Metadata for pathful RS and add explicit resourceServerUrl (RFC 9728) #858

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

blustAI
Copy link

@blustAI blustAI commented Aug 8, 2025

Fixes #600

  • Fixes a mismatch between the authorization server (issuer) and the protected resource (resource) in the OAuth 2.0 Protected Resource Metadata (PRM).
  • When the resource server (RS) has a path (e.g., http://host:port/mcp), PRM is now also served at /.well-known/oauth-protected-resource/<path> as required by RFC 9728.
  • Introduces optional resourceServerUrl in AuthRouterOptions with fallback: resourceServerUrl ?? baseUrl ?? issuer (keeps backward compatibility for AS=RS deployments).

Motivation and Context

  • Previously, PRM could emit the issuer value in the resource field and ignore the RS path.
  • For an RS like https://example.com/mcp clients expect PRM at https://example.com/.well-known/oauth-protected-resource/mcp, but received the base well-known without the path and with an incorrect resource.
  • This caused errors such as: “Protected resource … does not match expected … (or origin)” in real-world setups where the Authorization Server (AS) and Resource Server (RS) are separate (e.g., AS on https://auth.example.com, RS on https://example.com/mcp).
  • The change aligns the router with RFC 9728 and eliminates these mismatches.

How Has This Been Tested?

Local app with split roles:

Checks:

# Path-specific well-known (required when RS has a path)
curl -s http://localhost:5002/.well-known/oauth-protected-resource/mcp | jq
# → "resource": "http://localhost:5002/mcp"
# → "authorization_servers": ["http://localhost:4000/"]

# Base well-known remains available for compatibility
curl -s http://localhost:5002/.well-known/oauth-protected-resource | jq

OAuth authorization flow completed successfully; the “resource doesn't match expected” error disappeared.

Breaking Changes

None.

  • resourceServerUrl is optional.
  • Fallbacks preserve the previous behavior (AS=RS), so existing configurations continue to work.
  • Adding the path-specific well-known endpoint is additive.

Types of changes

  • [V] Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • [V] I have read the MCP Documentation
  • [V] My code follows the repository's style guidelines
  • [V] New and existing tests pass locally
  • [V] I have added appropriate error handling (N/A)
  • [V] I have added or updated documentation as needed (N/A)

Additional context

  • Implementation follows RFC 9728: PRM MUST be available at the URL formed by inserting /.well-known/oauth-protected-resource before the RS path; the resource value MUST exactly equal the RS identifier.
  • The helper getOAuthProtectedResourceMetadataUrl() is updated accordingly to construct the path-specific well-known URL.

@blustAI blustAI requested a review from a team as a code owner August 8, 2025 22:41
@blustAI blustAI requested a review from pcarleton August 8, 2025 22:41
@blustAI blustAI force-pushed the fix/router-prm-baseurl branch from c2cef38 to 9f5373b Compare August 8, 2025 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

mcpAuthRouter ignores path of baseUrl
1 participant