The short answer
MCP authorization is OAuth 2.1 applied to remote MCP servers. The MCP server is an OAuth resource server; the MCP client (Claude, Cursor, an agent framework) is the OAuth client; a separate or co-hosted authorization server signs the user in and issues tokens.1 The server publishes where its authorization server is with Protected Resource Metadata (RFC 9728), the client asks for a token bound to that one server with the resource parameter (RFC 8707), and PKCE protects the code exchange.11
It applies to HTTP transports. Local stdio servers should not use it and take credentials from the environment instead.1 And it answers “who is this client, acting for whom”, not “should this tool call run”.
Deedglass
A tool call meets your rules before it runs
Asks to run
DELETE FROM visits;
Deletes every row in visits
Deedglass checks your rules
- Reading dataAllowed
- Deleting a whole table (DROP, TRUNCATE)Never
- Changing or deleting rows without saying which (WHERE)This one
- Other changesWait for a person
Who plays which role
The spec builds on the OAuth 2.1 draft plus a short list of RFCs: 6750 (bearer tokens), 8414 (authorization server metadata), 7591 (dynamic registration), 8707 (resource indicators), 9728 (protected resource metadata) and 9207 (issuer identification), along with OpenID Connect Discovery and the Client ID Metadata Document draft.1
| Role | In MCP | Its job |
|---|---|---|
| Resource server | The MCP server | Accept only tokens issued for it1 |
| Client | The MCP client or agent host | Discover, register, get a token, send it on every request1 |
| Authorization server | Your IdP, or one built into the server | Sign the user in, issue tokens1 |
| Resource owner | The user | Consent to what the client may do |
Authorization is optional in MCP. A server that holds nothing sensitive can skip it.1 Once you support it over HTTP, the spec’s MUSTs apply.
The flow, step by step
Here is the path a client takes the first time it meets a protected server, following the spec’s sequence:
- The client calls the server without a token. The server answers
401with aWWW-Authenticateheader pointing at its Protected Resource Metadata, and ideally ascopehint.1 - The client reads the metadata at the URL given, which names the authorization server(s). Servers must publish this document and clients must use it to find the authorization server.1
- The client discovers the authorization server’s endpoints through RFC 8414 metadata or OpenID Connect Discovery; clients must support both.1
- The client gets a client ID, by one of three methods covered below.2
- The client opens the browser with an authorization request carrying a PKCE
code_challenge(S256), theresourceparameter naming the MCP server, and the chosen scopes. It records which issuer it expects.1 - The user signs in and consents. The authorization server redirects back with a code, and should include
iss.1 - The client checks
issagainst the issuer it recorded, then exchanges the code plus the PKCEcode_verifierand theresourceparameter for a token.1 - Every MCP request carries the token in the
Authorization: Bearerheader, never in the query string.1
Getting a client ID
Desktop and agent clients usually have no prior relationship with a server they’ve just been pointed at. The spec offers three ways to get a client ID, in this priority order for clients that support all of them:2
| Method | When | Status in 2026-07-28 |
|---|---|---|
| Pre-registration | Client and server already know each other | Supported2 |
| Client ID Metadata Documents | No prior relationship (the common case) | Should be supported1 |
| Dynamic Client Registration (RFC 7591) | Older authorization servers | Deprecated, kept for compatibility2 |
A Client ID Metadata Document turns the client ID into an HTTPS URL. The client hosts a small JSON file at that URL with its name and redirect URIs; the authorization server fetches it, checks that the client_id inside matches the URL exactly, and only accepts redirect URIs listed there.2 That removes the need for every server to run an open registration endpoint, which is where several earlier problems came from. Our post on the confused deputy problem shows one.
The rules that stop real attacks
Most of the MUSTs exist because of a specific, known attack:
| Rule | Stops |
|---|---|
Send resource (RFC 8707) in authorization and token requests1 |
A token for server A being replayed at server B |
| Servers must validate the token was issued for them, and must not accept or pass through other tokens1 | Token passthrough: a server forwarding your upstream token, or accepting one meant elsewhere |
PKCE with S256; refuse to proceed if the server doesn’t advertise code_challenge_methods_supported3 |
A stolen authorization code being redeemed by someone else |
Check iss against the recorded issuer1 |
Mix-up attacks, where a malicious authorization server collects a code issued by an honest one |
| HTTPS for authorization endpoints; redirect URIs must be localhost or HTTPS3 | Interception and open redirects |
| Tokens in headers, never query strings1 | Tokens leaking into logs and browser history |
The token passthrough rule deserves emphasis. If your MCP server calls GitHub or Salesforce on the user’s behalf, it gets its own token from that upstream service. It must not forward the token the MCP client gave it, and it must not accept a GitHub token from the client in place of its own.3
One rule isn’t in this list because it sits outside OAuth: clients must treat the authorization URL a server hands them carefully. The mcp-remote flaw, where a crafted authorization_endpoint from a malicious server led to command injection, is the cautionary tale4; see our write-up.
Scopes and step-up
Scopes are how a server says what a token allows. The spec asks servers to include a scope hint in the 401 challenge, and clients to request the minimum they need at first.1 When a token is too weak for a particular call, the server answers 403 with error="insufficient_scope" and the scopes required, and the client runs a step-up authorization for a broader token, keeping the scopes it already had.1
That’s a good pattern for agents. An agent can start with files:read, and when it tries to write, the user sees a fresh consent screen for files:write. It turns a hidden escalation into a visible one.
But scopes are coarse. files:write doesn’t say which file, how many, or whether the agent should be deleting the folder it’s in. That decision still has to happen somewhere else.
What authorization doesn’t cover
Authorization done well tells a server, reliably, which client is calling for which user, with which scopes. It does not tell anyone:
- Whether a particular call is a good idea. A correctly authorized agent with
db:writecan still runDELETEwithout aWHERE. - What actually changed. A token says nothing about the outcome of a call. If an agent says it updated one row, you still need to check.
- Anything about local servers. stdio servers take credentials from the environment and fall outside this spec.1 Most coding-agent setups still run local servers, with whatever keys sit in their config.
- Prompt injection. A properly scoped token used by a manipulated agent does what the attacker asked, within scope. See prompt injection.
That’s why authorization and per-call policy are separate layers. A gateway or the server itself decides call by call, ideally with an approval for risky ones. Our MCP server security basics puts the layers together.
A checklist for server builders
- Serve Protected Resource Metadata and return
401with aWWW-Authenticatepointer and ascopehint.11 - Validate every token’s audience is your server; reject everything else.1
- Never forward the client’s token upstream; get your own.3
- Keep
scopes_supportedminimal and use403 insufficient_scopefor step-up.1 - Prefer Client ID Metadata Documents over open dynamic registration.2
- Require PKCE S256, HTTPS endpoints and exact redirect URIs.3
- Add per-call policy and logs on top. Authorization says who; it doesn’t say what’s safe.
For what changed elsewhere in the latest revision, read our MCP 2026-07-28 summary. To try call-by-call approvals on a real database in your browser, open the playground; to grade the MCP servers and keys your agents can reach on your own machine, run npx deedglass scan (the grade, explained).
Written with AI assistance and checked against our claims register.