Security & Access Control
MCP Authentication and OAuth: A Practical Setup Guide
By Antoine van der Lee··Updated
MCP authentication starts with identifying which connection needs protection. For protected HTTP MCP endpoints, the authorization framework uses OAuth to obtain an access token for that endpoint. Local stdio servers instead use process-level credential delivery, such as environment variables. Neither a successful login nor possession of a token means the caller may use every tool or downstream resource.
This guide follows MCP revision 2026-07-28, checked in October 2026. It explains discovery, registration, the interactive authorization flow, and practical failure diagnosis. OAuth 2.1 and the MCP protocol revision are different version labels; “MCP 2.1” is not the revision used here. Treat older client support as an explicit compatibility requirement.
Separate three credential boundaries
A common integration has a client reaching an MCP server, which then reaches another API. You may also have a person signing into the client application. Those are separate relationships, even when the interface presents them as one “Connect” button.
| Boundary | What must be established | What does not follow automatically |
|---|---|---|
| Person to host application | The application's user identity and session | Permission to access any MCP endpoint |
| MCP client to protected MCP endpoint | A credential valid for that endpoint and permitted operation | Permission to every upstream API |
| MCP server to downstream service | A separate credential and appropriate downstream access | Permission for every caller to use it |
The MCP authorization specification makes authorization optional for implementations overall and defines its HTTP authorization framework. It recommends a different credential approach for stdio. Avoid saying that every MCP server must offer a browser OAuth flow, or that a local child process shares the client's complete trust boundary. A process receiving a secret still needs restricted permissions and safe diagnostics.
For the downstream boundary, see MCP credential injection. Keeping a token out of model context and checking a caller's authority are complementary controls.
Discover the authorization server from resource metadata
Begin with the protected MCP endpoint, not a guessed login URL. Its metadata identifies the authorization server or servers that can issue appropriate credentials. The authorization discovery requirements support a resource-metadata URL in a WWW-Authenticate challenge and well-known metadata locations. Clients must support both discovery mechanisms and follow the specified fallback order.
This illustrative challenge uses reserved example domains and no live credential:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource", scope="issues:read"
The scope is fictional and service-defined, not a standard MCP permission. Resource metadata and authorization-server metadata are different documents. After locating the issuer, the client discovers and validates its endpoints rather than assuming the MCP host also owns /authorize and /token.
Record safe diagnostic facts: requested endpoint, metadata status, issuer identifier, and client version. A metadata fetch failure occurs before token issuance; repeatedly requesting new tokens will not repair an unreachable or inconsistent metadata document.
Choose a registration method the issuer supports
Before the interactive flow, the client needs a client identifier recognized by the chosen authorization server. The current registration specification describes pre-registration, Client ID Metadata Documents, and Dynamic Client Registration. For clients supporting all options, available pre-registered information comes first, then advertised metadata-document support, then supported dynamic registration as a fallback.
Dynamic Client Registration is deprecated in this revision and retained for compatibility. Do not turn an old requirement to register dynamically into a universal setup instruction. Equally, do not assume a client supports newer metadata documents just because its server does; compatibility involves both participants.
Keep persisted issuer-specific registration credentials associated with their issuer. If an endpoint changes authorization servers, blindly reusing an old client secret can fail or disclose it to the wrong service. For registration errors, inspect supported methods, the client type, and exact redirect URI requirements. A guessed wildcard callback is not an acceptable fix.
Understand what PKCE protects
For an interactive authorization-code flow, PKCE binds code redemption to a verifier created by the client. The client sends a challenge during authorization and proves possession of the verifier when exchanging the returned code. RFC 7636 defines this mechanism to mitigate authorization-code interception; the S256 method hashes the verifier before encoding the challenge.
The practical division matters: a user completing consent is one step, and the client successfully redeeming the authorization code is another. A callback can arrive while redemption still fails because the verifier, redirect URI, client registration, or issuer context does not match. Do not paste the code or verifier into a support ticket to demonstrate that the browser redirected.
Use the client's documented flow and a tested OAuth implementation. This article is not replacement authentication code. Preserve the per-attempt context needed for callback validation, and keep separate attempts separate; a second sign-in tab should not accidentally redeem the first attempt's code. Diagnose the failing stage with redacted error categories.
Bind the token to its resource and permission
The target resource answers “where can this token be used?” Scope answers “what access is requested or granted there?” A broad scope does not make a token valid at another endpoint. RFC 8707 defines resource indicators, which MCP uses to identify the intended endpoint during authorization and token requests.
For example, a request for https://mcp.example.com/mcp should not silently become a request for https://api.example.com. Do not infer the resource from a friendly connection name. Keep a canonical resource identifier in trusted configuration and compare it against the actual token-validation requirements.
The MCP resource server must validate that the token is intended for itself. Token validation depends on the issuer's token format and supported validation mechanism; not every access token is a JWT that your application should decode locally. A server accessing a downstream API needs that API's separate credential. Forwarding an incoming bearer token across the boundary is not a substitute for authorization.
Use agent access-control guidance to connect granted permissions to actual tools and resources. Do not assume one scope string maps cleanly to every operation in a changing catalog.
Diagnose failures by stage, without relaxing validation
A useful failure report says where the flow stopped and which non-secret identifiers were involved. Start with the HTTP status and safe error code, then distinguish discovery, registration, callback validation, code exchange, token validation, and tool authorization. Bearer token error semantics in RFC 6750 distinguish invalid-token and insufficient-scope cases.
| Observation | Check first | Avoid |
|---|---|---|
| No sign-in flow starts | Metadata availability and advertised authorization support | Hardcoding a guessed issuer |
| Registration is rejected | Supported method, client type and redirect URI | Disabling redirect checks |
| Browser returns but connection fails | Callback context and code-exchange error category | Printing codes, verifiers or client secrets |
| Request returns invalid-token failure | Expiration, issuer and intended resource | Accepting a token just because its syntax looks correct |
| Token works for one operation only | Granted permissions and required operation scope | Requesting every available privilege by default |
| Login succeeds but a tool is denied | Tool policy and downstream authorization | Treating authentication as an allow-all decision |
| Old access continues after removal | Active tokens, refresh credentials and documented caches | Assuming logout revoked all issued credentials |
Use a sanitized handoff record so the next owner can investigate the stopped stage without repeating the whole login flow. The completed example below is fictional; its domains are reserved examples and issues:read is a service-defined permission, not a standard MCP scope.
| Handoff field | Fictional callback-arrived, exchange-rejected case |
|---|---|
| Last completed phase | Callback received and attempt context validated; code exchange rejected; token validation and tool authorization not reached |
| Intended MCP resource | https://mcp.example.com/mcp |
| Issuer and registration | https://auth.example.com; pre-registered client |
| Callback/redirect match | Registered callback matches the authorization request; redirect URI used during exchange still needs checking |
| Safe error category | Token endpoint returned invalid_grant; cause not yet established |
| Required versus granted permission names | Requested issues:read for the test read; no usable grant established, granted permissions unknown |
| Denied-call evidence reference | Restricted exchange-failure record EXAMPLE-AUTH-07; no tool call attempted, so no denied-tool evidence exists yet |
| Suspected owner and next check | Client integration owner compares the exchange's redirect URI and per-attempt PKCE/issuer context with the original request inside the restricted diagnostic environment |
Keep authorization codes, PKCE verifiers, client secrets, token values, cookies and Authorization headers out of this record. Internal resource/issuer endpoints and diagnostic details may also be sensitive: share restricted references instead of copying them into a public ticket. Record comparison results, not the values used to establish them.
In this example, the browser's return proves neither successful token issuance nor permission to call a tool. The error category narrows the investigation but does not establish which input was wrong. After repair, use a dedicated test identity and an innocuous read to record both an authorized request and a deliberate denial, then attach their safe evidence references. The audit log guide explains how to retain useful decision evidence without full payloads.
Operate authorization as a lifecycle
A connected status is a point-in-time observation. Access can change when a user leaves, the provider revokes a grant, a credential expires, a server moves, or the requested operation needs additional permission. Your integration needs an explicit response for each event rather than an unbounded sign-in or refresh loop.
Assign ownership for the connection, the issuer configuration, and downstream credentials. Define what the user sees when access is unavailable and how an operator can distinguish an expired credential from a denied action. Test revocation using the provider's documented behavior; token replacement, session logout, and grant revocation are not interchangeable operations.
If a gateway mediates the flow, validate the gateway and upstream relationships independently. The gateway buying guide supplies an evidence-based evaluation workflow. For MCP Beast, ask which authentication modes are implemented on the runtime you will use instead of assuming every mode described by the protocol is supported by the product.
Frequently Asked Questions
Does every MCP server require OAuth?
No. MCP authorization is optional overall, and the standard authorization framework is for HTTP-based transports. The specification recommends environment-based credential retrieval for stdio rather than using that HTTP flow.
Is OAuth 2.1 the same as an MCP protocol version?
No. OAuth 2.1 names the authorization framework referenced by MCP. This guide uses MCP revision 2026-07-28; clients and servers must separately support the protocol revision and authorization capabilities they use.
Why does a valid login still produce a denied tool call?
Login, access-token validation, tool authorization and downstream API permissions are separate checks. Identify which stage rejected the request, then inspect safe error details and required permissions without disabling validation.
Can I reuse an upstream API token to authenticate to an MCP server?
Not merely because the MCP server calls that API. The credential presented to the MCP endpoint must be valid for that endpoint; downstream access uses a separate appropriate credential. Do not implement token passthrough as a shortcut.
Use the MCP security overview to review the surrounding controls and the credential boundary guide to keep secret values out of agent-visible data.