OAuth 2.1 for MCP: What the Spec Standardised and What You Need to Know
The 2025-06-18 Model Context Protocol specification standardised on OAuth 2.1 with PKCE for every remote MCP server. The change cleans up a previously fragmented auth landscape and adds explicit guidance against confused-deputy attacks. Here is the practical guide to what changed, what your client has to implement, and what your server needs to expose.
Before the spec: every server, its own auth
Remote MCP servers before mid-2025 each defined their own auth. Some used static API keys passed in headers. Some used custom JWT flows. A few implemented OAuth 2.0 — and each of those used a different combination of flows, scopes, and token formats. MCP client authors had to implement an "auth model adapter" per server, which scaled poorly and made remote MCPs harder to ship than local stdio servers.
The 2025-06-18 spec replaced that mess with one rule: remote MCP servers MUST support OAuth 2.1 with PKCE for user-facing flows, and SHOULD support dynamic client registration. Clients now implement one flow and it works against every spec-compliant server.
The OAuth 2.1 handshake for MCP
- 1
Discovery
The client fetches the server's OAuth metadata (typically at /.well-known/oauth-authorization-server). This returns the authorization endpoint, token endpoint, registration endpoint, supported scopes, and PKCE methods.
- 2
Dynamic client registration
The client POSTs to the registration endpoint with its name, redirect URI, and the grant types it supports. The server returns a client_id (and optionally a client_secret for confidential clients). This step is skipped if the client is already registered.
- 3
Authorization request
The client generates a PKCE code verifier, derives the challenge, and opens the authorization endpoint in the user's browser with client_id, redirect URI, scope, and PKCE challenge. The user signs in to the upstream service and consents to the scopes.
- 4
Token exchange
The server redirects back to the client with an authorization code. The client POSTs the code plus the PKCE verifier to the token endpoint and receives an access token (and usually a refresh token). The server validates the verifier matches the original challenge before issuing tokens.
- 5
Tool calls
Subsequent JSON-RPC calls to the MCP server include the access token in the Authorization header. Refresh tokens are exchanged when the access token expires, using stricter rotation rules than OAuth 2.0 — each refresh issues a new refresh token, and the old one is invalidated.
Audience binding and the confused-deputy fix
The spec\'s most important security addition is explicit audience binding. Every access token an MCP server issues is bound to that server\'s audience identifier. If a downstream service calls a different MCP using that token, validation fails. This blocks the classic "I have your token, let me reuse it elsewhere" attack — the token is only valid for the audience it was minted for.
For server authors: include the audience claim in every token you issue and verify it on every request. For client authors: do not pass tokens between servers — request a fresh token per MCP via the OAuth flow even if the upstream service is the same.
What you have to implement
If you build an MCP client
- OAuth 2.1 authorization code flow with PKCE (required for every public client)
- Dynamic client registration when the server supports it
- OS-native credential storage (Keychain / DPAPI / libsecret)
- Refresh-token rotation handling
- Browser handoff for the authorization step (system browser, not embedded webview)
If you build a remote MCP server
- OAuth 2.1 authorization + token endpoints with PKCE validation
- Dynamic client registration endpoint (RFC 7591)
- /.well-known/oauth-authorization-server metadata
- Audience-bound access tokens
- Refresh-token rotation with single-use refresh tokens
- Scope enforcement on every MCP method, not just at the auth boundary
Migration path from API keys
If you maintain an MCP server that currently uses API keys, the spec allows you to support both during migration. Keep the API key path for backward compatibility, add the OAuth 2.1 path for new clients, and deprecate the API key path on a published timeline. Most servers complete the transition over one or two release cycles.
The carrot for users: OAuth 2.1 means no more environment-variable token management and no more credential rotation in config files. The carrot for you as a server author: scoped, revocable, audited access by default — the security posture upgrade pays for itself the first time a user accidentally commits a config file.
What not to do
- Do not implement OAuth 2.0 implicit flow. The spec mandates 2.1; 2.0 implicit is forbidden.
- Do not skip PKCE for "trusted" clients. PKCE is mandatory for public clients, period.
- Do not reuse access tokens across MCP servers. Each token is audience-bound for a reason.
- Do not store tokens in plaintext config files. Use the OS credential store.
- Do not use long-lived access tokens. Short-lived access + refresh rotation is the safer default.
Frequently asked questions
What did the 2025-06-18 MCP spec change about auth?
It standardised on OAuth 2.1 with PKCE for remote (HTTP-based) MCP servers, including dynamic client registration. Before this, every remote server defined its own auth model — API keys, custom tokens, ad-hoc OAuth flows — which made client implementations fragile. The new spec gives every client one auth handshake to implement.
Why OAuth 2.1 and not OAuth 2.0?
OAuth 2.1 is OAuth 2.0 with the deprecated and dangerous parts removed — implicit flow is gone, password grant is gone, PKCE is mandatory for public clients, and refresh tokens have stricter rotation requirements. Standardising on 2.1 means MCP clients do not have to support a permissive superset of OAuth, just the modern subset.
What is dynamic client registration and why does MCP need it?
Dynamic client registration lets an MCP client (Claude Desktop, Cursor, your custom agent) register itself with an MCP server at runtime instead of requiring the server's operator to pre-create a client ID. Without it, every new MCP client would need a manual onboarding step per server. With it, the user installs the MCP, the client registers, the OAuth flow runs, and the user is in.
What does the OAuth flow look like for an MCP user?
User installs the MCP in their client. Client discovers the auth endpoints via the server's metadata. Client dynamically registers itself. Client opens an OAuth 2.1 authorization request (with PKCE) in the user's browser. User signs in to the upstream service and approves the requested scopes. Client receives an authorization code, exchanges it for an access token, and stores it. Subsequent tool calls include the token.
What is the confused-deputy attack the spec warns about?
A confused deputy is when a privileged actor (the MCP server) is tricked by an unprivileged actor (a third party) into using its privileges in unintended ways. In MCP, the classic case is token passthrough: a server receives a token meant for it and re-uses that token to call a different service. The spec requires audience binding so tokens cannot be reused outside their intended audience.
Do local stdio MCPs use OAuth 2.1?
No. Local stdio servers run as subprocesses under the user's account and use whatever credentials the client passes in environment variables — typically API keys for the service the server wraps. OAuth 2.1 is for remote (HTTP) MCPs where the server and the user are on different hosts.
How do I store the OAuth tokens an MCP client receives?
In the OS credential store, not in a config file. Claude Desktop uses Keychain on macOS, DPAPI on Windows, libsecret on Linux. Cursor follows the same pattern. If you are building your own MCP client, use keyring-style libraries that wrap the OS store — never put long-lived tokens in plain files inside the project directory.
More guides
Fundamentals
What Is MCP? A Plain-English Guide to Model Context Protocol
6 min read
Setup Guide
Best MCPs for Cursor in 2026 (Ranked + Setup)
8 min read
Setup Guide
Best MCPs for Claude Desktop in 2026 (Ranked + Setup)
9 min read
Setup Guide
Best MCPs for Claude Code in 2026 (Ranked + Setup)
8 min read
Setup Guide
Best MCPs for Windsurf in 2026 (Cascade-Ready Setup)
8 min read
Setup Guide
Best MCPs for VS Code in 2026 (Agent Mode + .vscode/mcp.json)
8 min read
Strategy
MCP Registry vs Curated Directory: Which Should You Use?
5 min read
Setup Guide
Best MCPs for ChatGPT: The Apps and Connectors Worth Installing
9 min read
Tutorial
How to Add an MCP Server to ChatGPT (Developer Mode + Apps Directory)
7 min read
Security
MCP Security: What to Know Before You Install
9 min read
Role Guide
Best MCPs for Marketers in 2026 (SEO, Email, Analytics)
8 min read
Strategy
Remote vs Local MCP Servers: When to Use Each
7 min read
Fundamentals
MCP vs Function Calling: What’s the Difference?
6 min read
Comparison
MCP Directories Compared: Top MCPs vs mcp.so vs PulseMCP vs mcp.directory
8 min read
Security
MCP Prompt Injection: How Tool-Calling Agents Get Hijacked
8 min read
Security
Sandboxing MCP Servers: Containers, Least Privilege, and Process Isolation
9 min read
Security
Rotating MCP Credentials: A Practical Guide for Leaks, Expiry, and Routine Hygiene
7 min read
Security
Least-Privilege Scoping for MCPs: How to Grant the Smallest Useful Permission
7 min read
Setup Guide
Best MCP Servers for Databases in 2026 (Ranked + Setup)
10 min read
Setup Guide
Best MCP Servers for Research in 2026 (Search, Scrape, Synthesize)
9 min read
Setup Guide
Best MCP Servers for Design-to-Code in 2026 (Figma → React)
9 min read
Setup Guide
Best MCP Servers for Domains in 2026 (Registrars + DNS)
9 min read
Tutorial
How to Buy a Domain From Claude (Cloudflare MCP, Step by Step)
6 min read
Tutorial
How to Search for Domains With an AI Agent (Cross-Registrar Workflow)
7 min read