Skip to content

MCP Python SDK Implementation Gap-11: Server Missing Resource Validation for Token Acceptance #1443

@younaman

Description

@younaman

Initial Checks

Description

Summary

The MCP Python SDK server violates the specification requirement that "Authorization servers MUST only accept tokens that are valid for use with their own resources." The server accepts any token without verifying that the token's resource field matches the server's own resource URL.

Issue Details

Rule Violation

MCP Specification: "Authorization servers MUST only accept tokens that are valid for use with their own resources."

Current Implementation Analysis

1. Server Token Validation Flow

File: src/mcp/server/auth/middleware/bearer_auth.py

# Lines 30-49: BearerAuthBackend.authenticate()
async def authenticate(self, conn: HTTPConnection):
    # ... extract token ...
    
    # Validate the token with the verifier
    auth_info = await self.token_verifier.verify_token(token)
    
    if not auth_info:
        return None
    
    if auth_info.expires_at and auth_info.expires_at < int(time.time()):
        return None
    
    return AuthCredentials(auth_info.scopes), AuthenticatedUser(auth_info)
    # ❌ Missing: No validation of auth_info.resource against server URL

2. What's Currently Validated

The server only checks:

  • ✅ Token exists and is loaded successfully
  • ✅ Token is not expired
  • ✅ Token has required scopes (in RequireAuthMiddleware)

Missing critical validation:

  • ❌ Token resource field validation
  • ❌ Verification that token is intended for this server
  • ❌ Enforcement of "MUST only accept tokens valid for own resources"

3. Available Validation Tool

It's a little weird that I found the available validation function:
File: src/mcp/shared/auth_utils.py

# Lines 30-69: check_resource_allowed() function exists and is fully functional
def check_resource_allowed(requested_resource: str, configured_resource: str) -> bool:
    """ Check if a requested resource URL matches a configured resource URL.
    
    A requested resource matches if it has the same scheme, domain, port,
    and its path starts with the configured resource's path. This allows
    hierarchical matching where a token for a parent resource can be used
    for child resources.
    """

4. Evidence of Non-Usage

Grep search results show:

  • ✅ Function exists and is tested (36 test cases)
  • ✅ Used in client-side resource selection
  • ✅ Used in example server implementation
  • NOT used in core server authentication flow

Impact

  • Compliance Violation: Fails to meet MCP specification requirement
  • Security Risk: Server may accept tokens intended for other resources
  • Cross-Resource Token Leakage: Tokens for Server A could be used on Server B(maybe)

Root Cause

It appears that the server treats resource validation as not a mandatory rule, despite the specification's explicit "MUST" requirement. The validation tool exists but is not integrated into the core authentication flow.

Possible Solution

Add resource validation to BearerAuthBackend.authenticate():

async def authenticate(self, conn: HTTPConnection):
    # ... existing code ...
    
    auth_info = await self.token_verifier.verify_token(token)
    if not auth_info:
        return None
    
    if auth_info.expires_at and auth_info.expires_at < int(time.time()):
        return None
    
    # NEW: Validate token resource matches server resource
    if auth_info.resource:
        from mcp.shared.auth_utils import check_resource_allowed, resource_url_from_server_url
        server_resource = resource_url_from_server_url(conn.url)
        if not check_resource_allowed(requested_resource=server_resource, configured_resource=auth_info.resource):
            return None  # Token not valid for this server
    
    return AuthCredentials(auth_info.scopes), AuthenticatedUser(auth_info)

Files Affected

  • src/mcp/server/auth/middleware/bearer_auth.py (lines 30-49)
  • May need to import check_resource_allowed and resource_url_from_server_url

Example Code

Python & MCP Python SDK

latest

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Nice to haves, rare edge casesauthIssues and PRs related to Authentication / OAuthready for workEnough information for someone to start working on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions