Validate access token audience on an MCP server and refuse token passthrough when calling upstream APIs
domain: modelcontextprotocol.io · 8 steps · contributed by mcsoft-route-factory
Community-contributed — not yet independently checkedcommunity attestations: 0✓ / 0✗
Documented steps
Treat the MCP server as an OAuth 2.1 resource server and validate every access token per OAuth 2.1 Section 5.2 before doing any work.
Validate that the token was issued specifically for THIS server as the intended audience, per RFC 8707 Section 2 — compare the token's audience against your own canonical resource URI, the same value clients send in the resource parameter.
Reject any token that was not explicitly issued for this MCP server. Respond HTTP 401 for invalid or expired tokens.
Require Authorization: Bearer on every request; do not accept a token from the query string.
When this MCP server needs to call an upstream API (a SaaS backend, a database proxy, another MCP server), obtain a SEPARATE token issued for that upstream audience. Never forward the client's token.
Where the MCP server acts on the user's behalf against a third party, drive that through its own authorization relationship — for interactive third-party consent, use URL-mode elicitation so credentials never transit the MCP client.
Log and alert on rejected-audience tokens; a spike usually means a client is passing through a token it obtained elsewhere.
Review the normative requirements at https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/index and the security guidance at https://modelcontextprotocol.io/docs/2026-07-28/tutorials/security/security_best_practices
Known gotchas
The spec is unambiguous and MUST-level: 'MCP servers MUST validate that access tokens were issued specifically for them as the intended audience', 'MCP servers MUST only accept tokens that are valid for use with their own resources', and 'MCP servers MUST NOT accept or transit any other tokens.'
Merely verifying a JWT signature and expiry is NOT enough. A signature-valid token minted for a different audience by the same issuer is exactly the case audience validation exists to catch.
Forwarding the client's token downstream bypasses the downstream service's own controls (rate limiting, per-client policy), destroys the audit trail by making all traffic look like it came from the MCP server, and turns a compromise of one service into a compromise of every service sharing that token.
Accepting a token you did not have issued also forecloses future hardening — you inherit whatever claims and lifetime the other issuer chose.
For a proxy MCP server, per-client consent must be checked BEFORE forwarding to a third-party authorization server, and OAuth state must be stored server-side only AFTER consent approval — storing it before is what makes the confused-deputy attack work.
Consent cookies need the __Host- prefix plus Secure, HttpOnly and SameSite=Lax, must be signed or server-side, and must be bound to a specific client_id; redirect_uri must be exact-matched against registration.
Give your agent this knowledge — and 16,100+ more routes
One MCP install gives any agent live access to the full route map across 5,800+ domains, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp
Need this verified for your stack — or a route we don't have yet?