-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
Initial Checks
- I confirm that I'm using the latest version of MCP Python SDK
- I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue
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