Blog AI security

OAuth for MCP Servers: Authentication and Authorization Explained

A technical guide to implementing OAuth for remote Model Context Protocol servers without token passthrough, weak scopes, or confused deputy flaws.

OAuth for MCP Servers: Authentication and Authorization Explained, Infosec Writing Studio article image

OAuth for MCP servers lets a remote Model Context Protocol server verify which client is calling, which user or workload authorized it, and what access the resulting token permits. The MCP authorization specification treats the MCP server as an OAuth resource server, while a separate authorization server authenticates the user or workload and issues access tokens.

This separation matters because an MCP client can call tools that read data, change records, execute code, or reach other services. A connection that proves identity without limiting authority gives the client more access than it may need. OAuth supplies a standard process for obtaining, presenting, validating, and refreshing scoped credentials.

The MCP authorization specification applies this model to HTTP transports. Authorization is optional at the protocol level, but remote servers handling private data or consequential tools usually need it. Local servers using the standard input and output transport should receive credentials from their environment instead of running the HTTP OAuth flow.

Key Takeaways

  • Treat a protected MCP server as an OAuth resource server and use a separate authorization server to authenticate users or workloads.
  • Require PKCE, exact redirect URI matching, HTTPS, short token lifetimes, audience validation, and the OAuth resource parameter.
  • Never accept tokens intended for another service or pass an MCP client token through to an upstream API.
  • Design scopes around meaningful MCP capabilities, then enforce authorization again at the tool and resource level.

How OAuth Fits an MCP Connection

An MCP client first tries to reach the server or discovers that authorization is required from published metadata. The client then finds the correct authorization server, registers if necessary, sends the user through an authorization flow, and exchanges the returned code for an access token. It includes that token in later MCP HTTP requests.

OAuth does not define the user interface for approving every tool call. It establishes who issued the token, who received it, which protected resource it targets, and which scopes were granted. The MCP server must still decide whether a particular principal may call a particular tool with the supplied arguments.

The distinction between authentication and authorization is easy to blur. Authentication establishes the identity involved in the session, while authorization determines what that identity may do. A valid token can still be insufficient for a sensitive tool, a specific customer account, or a production resource.

MCP Authorization Discovery and Resource Indicators

The MCP specification uses OAuth metadata so clients do not need hard-coded authorization endpoints. A protected server can publish metadata following RFC 9728, and a 401 Unauthorized response can point the client to that metadata through the WWW-Authenticate header. The metadata identifies one or more authorization servers that can issue suitable tokens.

The client then reads authorization server metadata based on RFC 8414. That document can identify authorization and token endpoints, supported grant types, code challenge methods, and registration capabilities. Discovery reduces manual configuration, but clients must validate the discovered URLs and require HTTPS.

MCP clients also send the OAuth resource parameter defined by RFC 8707. Its value identifies the canonical MCP server URI for which the token is requested. The authorization server can then issue a token with a specific audience rather than a credential that works across unrelated services.

Resource indicators are a defense against token misuse. If a token requested for one MCP server is stolen or forwarded to another, audience validation should reject it. Both the authorization server and MCP server need consistent canonical resource identifiers for that check to work.

OAuth Flow for Human-Delegated MCP Access

Interactive MCP clients normally use the authorization code flow. The client opens the authorization server in a user agent, the user signs in and approves access, and the server redirects to the registered client URI with a short-lived authorization code. The client exchanges the code for tokens over a direct connection to the token endpoint.

Proof Key for Code Exchange, or PKCE, binds that authorization code to the client instance that started the flow. The client creates a random verifier, sends its derived challenge with the authorization request, and presents the verifier during the token exchange. A party that intercepts the code cannot redeem it without the verifier.

The client must also use an unpredictable state value and verify it on return. State connects the callback to the correct authorization attempt and helps prevent login cross-site request forgery. Redirect URIs should be registered exactly, with no permissive wildcard that sends codes to an attacker-controlled location.

Consent text should name the MCP server and describe the requested access in terms a user can understand. A scope called admin says little about whether the client can read repositories, modify cloud resources, or send messages. Approval is meaningful only when the requested authority is clear.

Machine OAuth for Unattended MCP Clients

Some MCP clients run as background services, scheduled jobs, build systems, or autonomous workloads with no user present. The MCP OAuth client credentials extension describes a machine-to-machine option for these cases. It is an opt-in extension, so clients and servers must confirm support instead of assuming it.

The extension supports client authentication with a shared secret or a signed JSON Web Token assertion based on RFC 7523. Signed assertions avoid sending a long-lived client secret on every token request and can support stronger key management. The private key still needs restricted storage, rotation, and an owner.

A workload token represents the application itself, not a human delegate. The server should therefore use different policies and audit fields for workload access. Attaching a human name to an unattended job can hide who actually controlled the credential at the time of an action.

Client credentials should not become a shortcut for unlimited service access. Issue a separate identity per deployment or job class, restrict its scopes, and keep token lifetimes short. This approach narrows the response when one workload or execution environment is compromised.

For deeper identity design, see the guide to AI identity infrastructure and the analysis of AI agent authorization and tool delegation.

Token Validation and Token Passthrough

The MCP client sends its access token in the HTTP Authorization: Bearer header on every protected request. Tokens must not appear in query strings because URLs can leak through logs, browser history, referrers, and monitoring systems. Transport encryption protects the header in transit, but the client and server must still avoid recording it.

The MCP server validates the token before trusting any claim. Validation should cover signature or introspection result, issuer, audience, expiration, activation time, and required scope. A token with a valid signature is unsafe if it was issued for another API or an untrusted issuer.

The specification explicitly forbids token passthrough. An MCP server must not take the token it received from a client and forward it to an upstream API. The upstream service may interpret the token differently, skip the MCP server’s policy, or accept authority that the user never meant to delegate.

If a tool needs another API, the MCP server should obtain a separate upstream credential through a defined delegation or service authorization process. It can associate that credential with the MCP session without confusing the two audiences. This boundary also produces clearer logs for the server and upstream provider.

A rejected or expired token should produce 401 Unauthorized. A valid token that lacks required permission should normally produce 403 Forbidden. Keeping those cases separate helps clients decide whether to refresh a token or ask for additional access.

OAuth scopes are the first permission boundary, but they should not be the last. A remote server might define scopes such as documents:read, documents:write, or deployments:execute. It should avoid one scope per small tool if that creates an approval screen nobody can interpret.

Tool authorization can then apply finer rules. A token with documents:write might permit updates only inside the user’s tenant, while a deployment tool might require a separate production role and an approval record. Arguments also matter because one tool can act on resources with very different sensitivity.

List and discovery responses need authorization too. Hiding an unauthorized tool from the advertised capability set can reduce accidental use and information exposure. The server must still reject a direct call because clients can cache tool lists or construct requests without discovery.

Human confirmation is useful for destructive or financially significant actions, but confirmation does not repair excessive token authority. The server should first verify that the caller is allowed to request the action. Confirmation then helps the user understand the specific operation before execution.

Secure MCP OAuth Implementation Checklist

  • Publish protected resource metadata and verify every discovered authorization URL uses HTTPS.
  • Use authorization code with PKCE for interactive public clients, plus exact redirect matching and state validation.
  • Include the canonical MCP server in the resource parameter and reject tokens with the wrong audience.
  • Validate issuer, signature, time claims, scopes, tenant context, and tool-specific policy on the server.
  • Store tokens outside logs and URLs, rotate refresh credentials, and use brief access token lifetimes.
  • Obtain separate credentials for upstream APIs and test that token passthrough attempts fail.
  • Give each unattended workload its own identity, restricted scopes, credential owner, and revocation process.
  • Record principal, client, tool, target resource, decision, and outcome without logging secrets or sensitive arguments.

The OWASP MCP Top 10 guide covers other server risks that sit beside OAuth, including tool poisoning, command injection, excessive permissions, and unsafe third-party integrations. Authorization should be tested with those failure modes, not treated as a complete MCP security program.

Common MCP OAuth Failure Modes

A common failure is accepting any token from a familiar identity provider. Without audience and issuer checks, a token meant for another internal application may open the MCP server. Test this condition with valid tokens that have the wrong resource, tenant, client, or scope.

Another failure is broad registration and redirect handling. Dynamic client registration can improve interoperability, but the authorization server needs controls for redirect URIs, client metadata, and registration abuse. Public clients cannot keep a secret, so their safety depends on PKCE, redirect validation, and careful callback handling.

Servers also make permission decisions only when issuing the token. Roles, tenant membership, resource ownership, and tool policy can change during the token lifetime. Keep access tokens brief and enforce current server-side policy where immediate revocation matters.

Finally, teams sometimes log full requests to debug agent behavior. Those logs may collect bearer tokens, authorization codes, tool arguments, and returned data. Redact credentials at ingestion and limit access to traces that contain sensitive MCP activity.

Frequently Asked Questions

Does every MCP server need OAuth?

No, the MCP protocol makes authorization optional and limits its HTTP authorization flow to remote HTTP transports. A local standard input and output server can obtain credentials from its execution environment. A remote server handling private data or sensitive actions should require a suitable authorization control.

Is an API key enough for an MCP server?

An API key can identify a client, but it usually lacks delegated user consent, standard scope discovery, short token lifetimes, and audience restriction. It may be acceptable for a narrow internal use case with careful storage and rotation. OAuth is a better fit when multiple users, clients, tenants, or permission levels are involved.

Can an MCP server reuse the client token for another API?

No, the MCP authorization specification forbids token passthrough to upstream services. The received token is intended for the MCP server and must be validated for that audience. The server should obtain a separate upstream credential through an explicit delegation or service authorization process.

Which OAuth flow should an unattended MCP client use?

An unattended client can use the MCP OAuth client credentials extension when both sides support it. A signed JWT assertion gives the authorization server a way to authenticate the client without a repeatedly transmitted shared secret. Each workload should receive limited scopes, short-lived tokens, and its own revocable identity.

Continue your research

Use the Reference Indexes for Definitions and Evergreen Guidance.

Editorial support

Need a Security Article Researched, Written, or Reviewed?