Skip to content

RFC 8707 Resource Indicators Implementation #991

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

Merged
merged 35 commits into from
Jun 23, 2025
Merged

RFC 8707 Resource Indicators Implementation #991

merged 35 commits into from
Jun 23, 2025

Conversation

ihrpr
Copy link
Contributor

@ihrpr ihrpr commented Jun 20, 2025

RFC 8707 Resource Indicators Implementation

Background:

Spec Changes PR
rfc8707
TS Implementation
Additional changes for not requiring strict matching

Closes: #962


Implements Resource Indicators validation for OAuth 2.0 (RFC 8707; spec change)
.

  • Set the resource parameter in OAuth authorization and token exchange flows to bind tokens to the MCP server
  • Updated token_verifier.py to show how to perform resource verification (disabled by default, run with --oauth-strict to enable)
  • Validation of resource uses hierarchical matching

Motivation and Context

Facilitate prevention of token theft/confusion attacks where a malicious MCP server steals tokens meant for other services by explicitly binding tokens to their intended resources and showing how a server can check this binding.

This security vulnerability was identified in modelcontextprotocol/modelcontextprotocol#544.

How Resource Indicators Work

Clients automatically include a resource parameter in their OAuth requests that identifies which MCP server they intend to access (e.g., resource=https://api.example.com/mcp). This happens transparently without any action from developers using the SDK.

Authorization Servers (AS) receive this resource parameter and include it in the tokens they issue, typically as the aud (audience) claim in JWT tokens. This cryptographically binds each token to its intended MCP server.

MCP Resource Servers (RS) can verify that incoming tokens were specifically issued for them by checking the audience claim matches their server URL. With --oauth-strict enabled, the server rejects tokens that don't include the correct resource identifier, preventing token confusion attacks.

Breaking Changes

While the change is breaking at a protocol level, it should not require code changes from SDK users (just SDK version bumping).

  • Client developers: No code changes required. The SDK automatically extracts and includes the resource parameter from the server URL
  • Server developers:
    • Resource validation is left to implementors (see token_verifier.py)
    • The Authorization Server (if external) needs to support / relay the resource param, and enough of the clients need to update their SDK to start setting the resource param in their auth requests. This is why server.py only validates the resource if --oauth-strict is set.
    • Each server should ideally treat each MCP server as a distinct resource in their PRM. If they host many servers under the same domain, the resource should be specific to a single server, not be domain-wide (otherwise any "bad apple" server might be able to benefit from resource confusion w/ its siblings).
  • Auth providers: should be updated to accept and relay resource parameter.

@ihrpr ihrpr marked this pull request as ready for review June 20, 2025 13:17
@ihrpr ihrpr requested review from ochafik and pcarleton June 20, 2025 13:18
@ihrpr ihrpr linked an issue Jun 20, 2025 that may be closed by this pull request
Copy link

@ochafik ochafik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, couple of nits + could benefit from more tests

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to add expectations on resource param to tests/client/test_auth.py similar to https://github.com/modelcontextprotocol/typescript-sdk/pull/638/files#diff-68dc66b14905d1fc01dc142e244a7e13fbdf88062d3a0b426983c333ccdfc9ed

(doesn't look like there's tests for authorize.py or for provider.py yet, not sure how hard they'd be to add)

@ihrpr ihrpr requested a review from ochafik June 20, 2025 14:27
ochafik
ochafik previously approved these changes Jun 20, 2025
Copy link

@ochafik ochafik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ihrpr !

Base automatically changed from ihrpr/auth2 to main June 23, 2025 13:19
@ihrpr ihrpr dismissed ochafik’s stale review June 23, 2025 13:19

The base branch was changed.

pcarleton
pcarleton previously approved these changes Jun 23, 2025
Copy link
Contributor

@pcarleton pcarleton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@ihrpr ihrpr merged commit 679b229 into main Jun 23, 2025
20 of 21 checks passed
@ihrpr ihrpr deleted the ihrpr/RFC-8707 branch June 23, 2025 16:10
@dr3s
Copy link
Contributor

dr3s commented Jun 24, 2025

Heads up that I'm going to submit a PR imminently to omit the resource parameter when the PRM is not available and the server version is 3-26-2025 or earlier. Just caught up with @pcarleton on the need to retain backwards compatibility for earlier servers.

Whether servers should be able to support more recent protocol versions without the resource parameter is an open question.

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.

Add requirement for RFC8707
4 participants