Why must an MCP server reject a token that was not issued for it (token passthrough)?
answer
- A token names its intended recipient
- Valid signature is not the same as for-me
- RFC 8707 asks for the binding
- Refuse borrowed tokens, both directions
- Upstream calls use the server's own credentials
basics
~20 sBecause a token names an intended audience, and honouring one issued for a different service turns the MCP server into a place any stolen or borrowed token can be spent. MCP requires audience-bound tokens, requested with the RFC 8707 resource parameter and validated on arrival.
solid answer
~50 sMCP revision 2026-07-28 requires tokens to be **audience-bound**: the client asks for a token scoped to this specific MCP server by sending the RFC 8707 `resource` parameter — the canonical MCP server URI from its protected-resource metadata — on the authorization and token requests, and the server validates on every call that the token it received names *itself* as the audience. Accepting anything else is **token passthrough**, and it is forbidden in both directions. Inbound, a server that accepts a token minted for some other API becomes a universal spending point for credentials it was never meant to see, and the real audience's consent, scopes and revocation no longer constrain anything. Outbound, an MCP server must not replay the caller's token to a downstream API; it obtains its own credentials for upstream calls. The practical failure it prevents: a bearer token leaked from any tenant or service being usable against your MCP endpoint simply because the signature verifies.
code
http · 5 linesPOST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOB&code_verifier=dBjftJeZ&redirect_uri=http%3A%2F%2F127.0.0.1%3A8765%2Fcb&resource=https%3A%2F%2Fmcp.example.com%2Fmcpgo deeper
Know that an access token is issued for one specific service and that an MCP server checks the token was meant for it, instead of accepting any token that looks valid.
Explain audience binding concretely: the client asks with RFC 8707's resource parameter, the server verifies the audience on every request, and a mismatch is rejected rather than tolerated because the issuer is trusted.
Show both directions of passthrough. Inbound acceptance of foreign tokens dissolves consent and revocation boundaries; outbound replay of the caller's token to an upstream breaks that service's own binding. Describe the server holding its own upstream credentials.
Own the boundary design across a fleet: one issuer, many resources, distinct audiences per MCP server, and a rule that no service forwards a credential it received. Be ready to say how you would audit for passthrough in existing deployments.
## What audience binding is An access token is not a general-purpose key; it is an assertion aimed at a specific recipient. The audience is the identity of that intended recipient, and validating it means the resource server asks "was this token minted for me?" and not merely "was this token minted by someone I trust?" MCP revision 2026-07-28 builds this into its authorization profile in two halves. **On the request side**, the client uses RFC 8707's `resource` parameter to tell the authorization server which resource the token is for. The value it sends is the canonical MCP server URI it learned from the server's protected-resource metadata during discovery. The authorization server mints a token whose audience is that resource. **On the validation side**, the MCP server must verify that the token presented on a request identifies it as the audience, and reject the request otherwise. The specification is explicit that a server must not accept tokens that were not issued for it. ## What goes wrong without it Call the missing check what it is: the server has downgraded from "is this token for me" to "is this signature valid". In any deployment where several services share one identity provider — which is nearly all of them — that means a token minted for the analytics API, the internal admin API or another tenant's MCP server will be accepted at your endpoint. Every one of those tokens was issued after a consent screen describing a *different* service, so whatever the user agreed to no longer bounds what happens. Scopes stop meaning anything portable, because the same scope string means different things at different resources. And when the real audience revokes a compromised token, that revocation may never reach you. The attack shape people picture is a stolen token, but the mundane version is worse: an integration that already legitimately holds a token for service A and points it at your MCP server because it happened to work. ## The outbound half: don't replay the caller's token Token passthrough has a second direction that trips up MCP servers specifically, because an MCP server is usually a facade over some other API. It is tempting to take the bearer token the client presented and forward it upstream. MCP forbids that. The reason is that the upstream API's audience check should fail — and if it does not, the whole chain has abandoned audience binding. Beyond the standards argument, forwarding means the upstream service's logs attribute activity to a client that never spoke to it, the MCP server can no longer apply its own policy between the caller and the upstream, and a compromise of the MCP server yields tokens usable elsewhere rather than tokens usable only against the MCP server. The correct pattern is that an MCP server holds credentials of its own for each upstream it calls, obtained through its own flow, and maps the authenticated caller onto the appropriate upstream identity or account. What crosses the boundary is a decision the MCP server made, not a credential it borrowed. ## How to validate, mechanically On each request the server verifies the token's issuer and signature against the authorization server it trusts, checks expiry, checks that the audience identifies this MCP server by its canonical URI, and then checks scopes for the specific method and tool being invoked. If the audience does not match, that is a `401`-class rejection, not a `403` — the credential is not usable here at all, rather than usable but under-privileged. Because revision 2026-07-28 removed protocol-level sessions and the `initialize` handshake, none of this can be done once and remembered for a connection. Every request is self-contained and independently authorized, which is what allows any node behind a load balancer to serve any request — and which makes cheap local validation against cached signing keys the practical implementation. ## Common misreadings - *"The signature is valid, so the token is fine."* Signature proves origin, not intent. - *"Our identity provider is internal, so all its tokens are equivalent."* A single issuer serving many resources is the exact condition under which the audience check matters most. - *"We validate the audience, so we can forward the token upstream."* Those are separate rules; forwarding breaks the upstream's audience binding. - *"Scopes are enough."* Scope strings collide across resources; only the audience says which resource a scope was granted at. ## The one-line version to say out loud Ask for a token bound to this MCP server with the `resource` parameter, verify on every request that the token names this server as its audience, refuse everything else, and never forward the caller's token to anything downstream.
- How does the client get a token bound to the right audience in the first place?It sends RFC 8707's `resource` parameter on the authorization and token requests, carrying the canonical MCP server URI it read from the server's protected-resource metadata during discovery. The authorization server mints a token whose audience is that resource, which is exactly the value the MCP server will check on arrival.
- Your MCP server fronts an internal REST API. Why not just forward the caller's token to it?Because that is outbound token passthrough. The upstream's own audience check should reject a token minted for the MCP server, and if it does not, the chain has abandoned audience binding entirely. The server should hold its own credentials for the upstream and map the authenticated caller onto the right upstream identity, so what crosses the boundary is a decision rather than a borrowed credential.
- Audience mismatch — is that a 401 or a 403?A 401. The credential is not usable at this resource at all, which is an authentication-layer rejection. A 403 with `error="insufficient_scope"` is for a token that is genuinely for this server but lacks the permission the specific call needs; conflating the two misleads clients, since one calls for a new flow against a different audience and the other for a step-up on the same one.
saying these in an interview costs you the question
- Accepts any token whose signature verifies
- Forwards the caller's token to downstream APIs
- Thinks a shared identity provider makes audiences interchangeable
- Relies on scopes alone without checking the audience
- Validates the audience once per connection rather than per request