MCP Authorization Explained: How OAuth 2.1 Lands in MCP (2026-07-28 Spec)
The MCP authorization spec clause by clause: role mapping, RFC9728 discovery, three registration mechanisms, the iss validation table, resource parameters, token red lines, and the step-up authorization flow.
How to
Fetch protected resource metadata
Request the RFC9728 Protected Resource Metadata from the protected MCP server to locate its authorization server, then obtain endpoints and capabilities via RFC8414 or OIDC Discovery (clients must support both).
Obtain a client ID
Use one of the three registration mechanisms by priority: Client ID Metadata Documents, pre-registration, or Dynamic Client Registration (RFC7591 -- deprecated, compatibility only).
Send resource-scoped authorization requests
Include the RFC8707 resource parameter in both authorization and token requests, set to the MCP server's canonical URI (lowercase scheme/host, no trailing slash); record the PKCE verifier and issuer in the same request context.
Validate the authorization response
Validate iss per RFC9207: reject when advertised but absent; when present, string-compare against the recorded issuer with no case folding or normalization; the validation applies to error responses too.
Use tokens correctly
Send Authorization: Bearer on every request, never in the query string; only send tokens issued by the target server's authorization server, always with the resource parameter.
Handle scope challenges
Pick initial scope from the 401 challenge first, scopes_supported as fallback; on runtime 403 + insufficient_scope, run step-up with the challenged scopes while keeping previously granted ones.
Remote MCP servers face real users and real data, which makes authorization unavoidable. The Authorization chapter of the 2026-07-28 spec version (verified 2026-09-03) standardizes it: MCP invents no new protocol -- it stands on the OAuth 2.1 draft and a row of RFCs, specifying a selective subset: what role the MCP server plays, how clients discover and register with authorization servers, how tokens travel, and how scopes stay minimal. This article unpacks the spec from an implementer's perspective; every MUST and SHOULD here is quoted from the specification.
1. First: Who Plays Which Role, and Who Needs OAuth
The role mapping is clean:
| MCP world | OAuth world |
|---|---|
| Protected MCP server | OAuth 2.1 resource server |
| MCP client | OAuth 2.1 client |
| Authorization server | Interacts with the user and issues access tokens; implementation details out of scope |
Authorization is optional, treated differently by transport:
- HTTP-based transport implementations SHOULD conform to the spec;
- stdio transport implementations SHOULD NOT -- credentials come from the environment (the same mechanism as the "limited env inheritance" note in our Debugging MCP in Practice: Inspector, Logging Rules, and the Connection Troubleshooting Chain);
- alternative transports MUST follow their protocol's established security best practices.
2. The Standards Base: Which OAuth Pieces MCP Uses
The spec declares itself a selective subset of these standards (list quoted from the spec):
| Standard | Role in MCP authorization |
|---|---|
| OAuth 2.1 (draft-ietf-oauth-v2-1-13) | Base: authorization servers MUST implement it |
| RFC 6750 | Bearer token usage + WWW-Authenticate scope challenges |
| RFC 8414 / OIDC Discovery | Authorization server metadata discovery (server provides at least one; clients must support both) |
| RFC 7591 | Dynamic Client Registration (deprecated, MAY, compatibility only) |
| RFC 8707 | The resource parameter: naming the token's target resource |
| RFC 9728 | Protected Resource Metadata: servers MUST implement, clients MUST use |
| RFC 9207 | The iss parameter: authorization response validation |
| Client ID Metadata Documents (draft) | Preferred registration mechanism (SHOULD support) |
3. Discovery and Registration: Two MUSTs and Three Routes
Discovery: the protected MCP server MUST implement RFC 9728, advertising its authorization server through Protected Resource Metadata; the client MUST use that metadata for discovery, then perform authorization server metadata discovery for endpoints and capabilities.
Registration: before initiating the flow, the client MUST obtain a client ID through one of three mechanisms -- Client ID Metadata Documents, pre-registration, or Dynamic Client Registration (RFC 7591). Note the spec's verdict on dynamic registration: deprecated, retained for backwards compatibility with authorization servers that do not support Client ID Metadata Documents; new implementations SHOULD use Client ID Metadata Documents.
4. Validating the Authorization Response: The iss Table
Before redirecting the user-agent, the client MUST record the issuer from the validated metadata document alongside the PKCE verifier in the same per-request record -- the validation relies on that record being authentic. Authorization servers SHOULD include iss in responses (RFC 9207), advertising it via authorization_response_iss_parameter_supported. The client's decision table (quoted from the spec):
| iss advertised | iss in response | Client action |
|---|---|---|
| true | present | Compare with the recorded issuer (simple string comparison, RFC 3986 §6.2.1) |
| true | absent | Reject the response |
| false / absent | present | Compare with the recorded issuer |
| false / absent | absent | Proceed |
Three details: the comparison must not apply case folding, default-port elision, trailing-slash, or percent-encoding normalization; a future revision is expected to upgrade iss from SHOULD to MUST (implementers are encouraged to emit and validate now); and the validation applies equally to error responses -- on mismatch, the client MUST NOT act on or display error, error_description, or error_uri.
5. The Resource Parameter: Tokens Issued for One Server
Clients MUST implement RFC 8707's resource parameter: include it in both authorization and token requests, with the target MCP server's canonical URI (lowercase scheme and host; implementations SHOULD accept uppercase for robustness), regardless of authorization server support.
Valid canonical URI examples (quoted from the spec):
https://mcp.example.com/mcp
https://mcp.example.com
https://mcp.example.com:8443
https://mcp.example.com/server/mcp (when a path is needed to distinguish servers)
Invalid examples:
mcp.example.com (missing scheme)
https://mcp.example.com#fragment (contains a fragment)
The spec also recommends: trailing-slash and non-trailing-slash forms are both valid absolute URIs, but consistently use the form without the trailing slash for better interoperability unless it is semantically significant. In an authorization request: &resource=https%3A%2F%2Fmcp.example.com.
6. Token Red Lines
Client side:
GET /mcp HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
- The token must ride in the
Authorization: Bearerheader, on every request from client to server; - The token MUST NOT be placed in the URI query string.
Server side (the MCP server as resource server):
- Validate tokens per OAuth 2.1, and MUST validate the audience (RFC 8707 §2 -- was this token issued for this server?);
- Invalid or expired tokens get HTTP 401;
- Clients MUST NOT send tokens not issued by that server's authorization server;
- Servers MUST NOT accept or transit any other tokens -- the formal clause against the Token Passthrough anti-pattern (see MCP Security Guide: The 8 Official Attack Vectors and Their Mitigations).
7. Scopes: Minimization and Step-Up
Initial scope selection priority (clients SHOULD follow least privilege):
- Prefer the
scopein the 401WWW-Authenticatechallenge (RFC 6750 §3); - Otherwise use
scopes_supportedfrom the Protected Resource Metadata (omitting the parameter if undefined).
Two MUST-level constraints: clients MUST NOT assume any set relationship between the challenged scopes and scopes_supported (either may be a subset, superset, or neither) -- the challenged scopes are authoritative for the current operation; and scopes_supported represents the minimal baseline, with extra permissions obtained incrementally via the step-up authorization flow. The standard 401 shape:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource",
scope="files:read"
8. Runtime Shortfalls and Error Codes
| Status | Meaning | Usage |
|---|---|---|
| 401 | Unauthorized | Authorization required, or token invalid |
| 403 | Forbidden | Invalid scopes or insufficient permissions |
| 400 | Bad Request | Malformed authorization request |
At runtime with an insufficient-scope token: the server returns 403 plus WWW-Authenticate with error="insufficient_scope", the minimum required scope set, and resource_metadata (consistent with 401 responses). The client then runs step-up: requests the additional scopes, SHOULD keeping previously granted ones so other operations keep working.
Refresh token rules worth remembering: clients MUST keep refresh tokens confidential in transit and storage, SHOULD declare refresh_token in their grant_types metadata, MAY add offline_access when it appears in the server's scopes_supported, and MUST NOT assume refresh tokens will be issued; servers SHOULD NOT include offline_access in WWW-Authenticate or scopes_supported (it is not a resource requirement).
9. Common Mistakes and Troubleshooting
- Putting OAuth on a stdio server: the spec says stdio SHOULD NOT -- credentials from the environment; do not force the HTTP flow onto local processes.
- Tokens in the query string: explicitly forbidden; Authorization header only.
- Omitting the resource parameter: "the server doesn't support it" is not an exemption -- MUST send, with the canonical URI.
- Skipping audience validation: accepting tokens minted for other resources is the entry point for Token-Passthrough-class risks.
- Normalizing before the iss comparison: case folding, trailing slashes, and port elision all break the comparison semantics -- simple string comparison only.
- Treating scopes_supported as a full catalog: it is the minimal baseline; extra permissions go through step-up.
10. Next Steps
- Implementation-level attack surfaces beyond authorization: MCP Security Guide: The 8 Official Attack Vectors and Their Mitigations.
- Debugging authorization and connection problems: Debugging MCP in Practice: Inspector, Logging Rules, and the Connection Troubleshooting Chain.
- The protocol itself and its architecture: Model Context Protocol: how MCP works and how to build on it.
Key points
- Role mapping: the protected MCP server is an OAuth 2.1 resource server; the MCP client is an OAuth 2.1 client; the authorization server's implementation details are out of scope (it may be hosted with the resource server or separately)
- Authorization is OPTIONAL: HTTP transports SHOULD conform; stdio transports SHOULD NOT (credentials come from the environment); alternative transports MUST follow their protocol's security best practices
- Discovery and registration: MCP servers MUST implement RFC9728 Protected Resource Metadata and clients MUST use it for authorization server discovery; registration is one of three -- Client ID Metadata Documents (SHOULD support), pre-registration, or Dynamic Client Registration RFC7591 (MAY, deprecated, kept for compatibility)
- Authorization response validation: clients MUST record the issuer and validate iss per RFC9207; a four-row decision table (including rejecting when advertised but absent); no case folding, default-port elision, or other normalization before comparison
- Token red lines: only in the Authorization: Bearer header on every request; MUST NOT go in the URI query string; the RFC8707 resource parameter (canonical URI, no trailing slash preferred) MUST be sent; servers MUST validate audience and MUST NOT accept or transit other tokens
- Scope minimization plus step-up: the 401 challenge scope is authoritative for the current request (clients MUST NOT assume any set relationship with scopes_supported); runtime shortfalls return 403 with error=insufficient_scope and the required scopes
Frequently asked questions
Official references
Related articles
Debugging MCP in Practice: Inspector, Logging Rules, and the Connection Troubleshooting Chain
The official method for debugging MCP integrations: the Inspector UI as first stop, stdio vs Streamable HTTP logging rules (notifications/message deprecated in spec 2026-07-28), startup root causes, and a five-step connection chain.
Read articleMCP Security Guide: The 8 Official Attack Vectors and Their Mitigations
The official MCP security best practices, decoded: eight attack classes from Confused Deputy and Token Passthrough to SSRF and scope minimization, each with the official mitigation requirements.
Read articleMCP server development: protocol, debugging, security, and production deployment
MCP server production essentials: protocol deep-dive (JSON-RPC 2.0 / lifecycle / capabilities negotiation), Inspector debugging, transport selection (stdio / Streamable HTTP / SSE), security modes (prompt injection / OAuth scope / audit).
Read articleSubscribe to GPTMap Weekly
One email every Monday: curated OpenAI updates, deep dives, and best practices. No ads, unsubscribe anytime.