How authorization works for remote MCP servers
MCP authorization is OAuth 2.1 applied to MCP servers reached over HTTP. The MCP server is an OAuth resource server. Clients get an access token from an authorization server and send it with every request, and the server must check that the token was issued for it. That binding is also why token passthrough, forwarding a client's token to a downstream API, is forbidden.
Authorization is optional in MCP. Servers that run locally over stdio should not use this flow and should take credentials from their environment instead. The rules below come from the 2026-07-28 revision, which aligns the flow more closely with OAuth and OpenID Connect.
A client that calls a protected server without a token gets a 401 challenge like this one, which tells it where to start:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource",
scope="files:read"The authorization flow, step by step
From that challenge, the client works through these steps:
- The client reads the server's Protected Resource Metadata (RFC 9728) to find its authorization server.
- It then loads that authorization server's metadata through OAuth 2.0 Authorization Server Metadata (RFC 8414) or OpenID Connect Discovery. Clients must support both.
- The client identifies itself with a Client ID Metadata Document or a pre-registered client ID. Dynamic Client Registration still works but is now deprecated.
- The user signs in and approves in the browser. The client must use PKCE, with the S256 method where it can, and must refuse to continue if the authorization server does not advertise PKCE support.
- The authorization request and the token request both carry a resource parameter (RFC 8707) set to the MCP server's canonical URI, such as https://mcp.example.com.
- If the authorization response includes an iss value, the client compares it with the issuer it recorded before redirecting (RFC 9207). This defends against mix-up attacks, in which a malicious authorization server tries to obtain a code issued by an honest one.
- The client sends the token in an Authorization: Bearer header on every request, never in the URL query string.
Audience binding: one token, one server
The resource parameter asks the authorization server to bind the token to one audience, the MCP server's URI. Each server must then confirm that a token was issued specifically for it, and invalid or expired tokens get a 401.
The specification is blunt about it. MCP servers must only accept tokens valid for their own resources and must not accept or transit any other tokens. Clients, in turn, must not send a server tokens from any authorization server other than that server's own.
Binding only works when the authorization server supports resource indicators. Clients must send the parameter anyway, so binding takes effect as soon as the server adds support. Where it works, a token stolen from one MCP server is useless at any other service that checks audiences.
What token passthrough is and why it is banned
Token passthrough is when an MCP server accepts a token that was not issued to it and forwards it unchanged to a downstream API. For example, a server that wraps a code-hosting API might receive a token for that API from the client and replay it on every upstream call.
The authorization specification forbids this, and MCP's security best practices give the reasons:
- Confused deputy: the downstream API may treat the request as if the MCP server had vetted it, or assume someone validated the token. Anyone holding a stolen token can then use the server as a proxy to pull data out.
- Lost audit trail: the MCP server cannot tell its clients apart when they all present opaque upstream tokens. Downstream logs show a different identity from the server making the calls.
- Bypassed controls: rate limits, request validation or monitoring that depend on the token audience stop applying when clients can use tokens directly against the downstream API.
- Wider blast radius: when several services accept the same token without checking its audience, compromising one service exposes the others.
What to do instead
When an MCP server needs an upstream API, it becomes an OAuth client of that API in its own right. It uses a separate token issued by the upstream authorization server, and the token it received from the MCP client never leaves the MCP server.
The specification does not prescribe how the server obtains that upstream token. One route is a separate consent flow in which the user authorizes the upstream API. Another is OAuth 2.0 Token Exchange (RFC 8693), where the upstream authorization server supports it.
Proxy servers that use one static client ID with a third-party authorization server need an extra control. They must get the user's consent for each dynamically registered MCP client before forwarding to the third party. Without it, a consent cookie from an earlier approval can be reused to send an authorization code to an attacker.
Keep scopes small too. Request the scopes named in the server's WWW-Authenticate challenge, and avoid wildcard scopes such as *, all or admin. When a privileged tool is first used, the server can ask for more with a 403 insufficient_scope challenge. The MCP Security & Configuration Auditor flags configurations that declare token passthrough.