Description
Description
Per the spec, MCP servers MUST validate that access tokens were issued specifically for them as the intended audience, according to RFC 8707 Section 2.
In the current SDK, the default TokenVerifier (ProviderTokenVerifier) returns an AccessToken from the provider without checking that AccessToken.resource matches the server’s canonical URI.
Evidence
# 301:306:src/mcp/server/auth/provider.py
class ProviderTokenVerifier(TokenVerifier):
async def verify_token(self, token: str) -> AccessToken | None:
return await self.provider.load_access_token(token)
# 37:43:src/mcp/server/auth/provider.py
class AccessToken(BaseModel):
...
resource: str | None = None # RFC 8707 resource indicator
# 22:41:src/mcp/server/auth/middleware/bearer_auth.py
auth_info = await self.token_verifier.verify_token(token)
# middleware does not check audience; relies on TokenVerifier
Impact
Servers may accept tokens not intended for this MCP resource (wrong audience), violating the MUST requirement.
Proposed remediation
- In ProviderTokenVerifier.verify_token, after loading the token, compare AccessToken.resource with the server’s canonical URI (e.g., AuthSettings.resource_server_url), using normalization and boundary-safe matching (mcp.shared.auth_utils.resource_url_from_server_url, check_resource_allowed). Reject on mismatch.
- Alternatively, add an audience-validation hook in RequireAuthMiddleware post-verification.
References
No response
Description
Description
Per the spec, MCP servers MUST validate that access tokens were issued specifically for them as the intended audience, according to RFC 8707 Section 2.
In the current SDK, the default TokenVerifier (ProviderTokenVerifier) returns an AccessToken from the provider without checking that AccessToken.resource matches the server’s canonical URI.
Evidence
Impact
Servers may accept tokens not intended for this MCP resource (wrong audience), violating the MUST requirement.
Proposed remediation
References
No response