Skip to content

MCP Python SDK Implementation Gap-10: MCP Python SDK Client Missing Token Issuer Validation #1442

@younaman

Description

@younaman

Initial Checks

Description

Summary

The MCP Python SDK client violates the specification requirement that "MCP clients MUST NOT send tokens to the MCP server other than ones issued by the MCP server's authorization server." The client only validates token existence and expiration, but does not verify that tokens were issued by the target server's authorization server.

Issue Details

Rule Violation

MCP Specification: "MCP clients MUST NOT send tokens to the MCP server other than ones issued by the MCP server's authorization server."

Current Implementation Analysis

1. Token Validation Logic

File: src/mcp/client/auth.py

# Lines 127-133: OAuthContext.is_token_valid()
def is_token_valid(self) -> bool:
    """Check if current token is valid."""
    return bool(
        self.current_tokens
        and self.current_tokens.access_token
        and (not self.token_expiry_time or time.time() <= self.token_expiry_time)
    )

2. Token Sending Logic

File: src/mcp/client/auth.py

# Lines 503-504: OAuthClientProvider.auth_flow()
if self.context.is_token_valid():
    self._add_auth_header(request)

# Lines 469-472: OAuthClientProvider._add_auth_header()
def _add_auth_header(self, request: httpx.Request) -> None:
    """Add authorization header to request if we have valid tokens."""
    if self.context.current_tokens and self.context.current_tokens.access_token:
        request.headers["Authorization"] = f"Bearer {self.context.current_tokens.access_token}"

3. What's Currently Validated

The is_token_valid() method only checks:

  • ✅ Token object exists (self.current_tokens)
  • ✅ Access token field exists (self.current_tokens.access_token)
  • ✅ Token is not expired (time.time() <= self.token_expiry_time)

4. What's Missing

Critical validation missing:

  • ❌ Token issuer verification
  • ❌ Check if token was issued by target server's authorization server
  • ❌ Validate token belongs to current server connection
  • ❌ Enforce "MUST NOT send" rule for wrong issuer tokens

Impact

  • Compliance Violation: Fails to meet MCP specification requirement
  • Security Risk: Client may send tokens intended for other servers

Root Cause

The client treats token validation as a simple existence/expiration check, ignoring the specification's explicit requirement for issuer validation before sending tokens.

Proposed Solution

Maybe SDK maintainers could enhance is_token_valid() to include issuer validation:

e.g., just a PoC

def is_token_valid(self) -> bool:
    """Check if current token is valid and issued by target server."""
    if not (self.current_tokens and self.current_tokens.access_token):
        return False
    
    # Check expiration
    if self.token_expiry_time and time.time() > self.token_expiry_time:
        return False
    
    # NEW: Check issuer matches target server
    if not self._is_token_issued_by_target_server(self.current_tokens.access_token):
        return False
    
    return True

def _is_token_issued_by_target_server(self, token: str) -> bool:
    """Verify token was issued by the target server's authorization server."""
    # Implementation depends on token format (JWT vs opaque)
    # For JWT: parse and verify 'iss' claim
    # For opaque: validate against stored issuer metadata
    pass

Files Affected

  • src/mcp/client/auth.py (lines 127-133, 503-504, 469-472)

Example Code

Python & MCP Python SDK

latest

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Broken core functionality, security issues, critical missing featurePR welcomePRs for this issue are welcome and will be reviewed by maintainersauthIssues and PRs related to Authentication / OAuthbugSomething isn't workinggood first issueGood for newcomersready 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