The MCP authorization spec names a failure mode that matters well beyond the protocol itself. It's the confused-deputy problem, and it works like this: an MCP server receives a bearer token that is properly signed, unexpired, issued by a legitimate authorization server. The server checks validity and lets the request through. Then it forwards that same token to a downstream API.
Every check passed. The wrong checks.
The token was never issued for that server. It was issued for a different service entirely, and the MCP server accepted it because it asked "is this token valid?" instead of "was this token issued for me?" One of those is a cryptographic question; the other is a relational one, and skipping it means you've built a replay surface into your architecture.
The spec is explicit about this: servers MUST validate that tokens were intended for them specifically, and MUST NOT pass client tokens through to upstream APIs. Each hop requires its own token, its own authorization relationship. A valid token with no audience binding is just a skeleton key that happens to be well-formatted.
What the spec requires:
- Clients MUST include resource indicators (RFC 8707) identifying the intended server in every token request
- Servers MUST reject tokens that don't include them in the audience claim
- Bearer tokens MUST appear in every HTTP request, even within a single session
What the spec forbids:
- Token passthrough — forwarding a client's token to upstream APIs without obtaining a separate token
- Accepting tokens with incorrect or missing audience claims
- Including access tokens in URI query strings
Why passthrough breaks things:
A forwarded token lets the downstream API assume the MCP server validated it. Rate limiting, audit trails, and trust boundaries all break because accountability can't be traced per-hop.
The proxy attack variant:
When an MCP proxy uses a static client ID, an attacker can craft a malicious redirect URI. If the authorization server remembers consent via cookies, the consent screen gets skipped, and the authorization code lands on the attacker's server.

