# MCP authorization makes an HTTP server an OAuth resource server that advertises its authorization server via 401 and RFC 9728 metadata

> In MCP specification 2026-07-28, a protected HTTP server acts as an OAuth 2.1 resource server: it answers 401 with a WWW-Authenticate pointer to its Protected Resource Metadata, and clients then discover the authorization server, register, use PKCE and RFC 8707 resource indicators, and send bearer tokens that the server must check for audience.

## Answer

In MCP, authorization is optional and applies to HTTP transports. A protected MCP server is an **OAuth 2.1 resource server**. It must publish OAuth 2.0 Protected Resource Metadata (RFC 9728) that names at least one authorization server in `authorization_servers`. An unauthenticated request gets `401` with a `WWW-Authenticate` header that can carry a `resource_metadata` URL. The client discovers the authorization server, registers, runs an authorization code flow with PKCE and an RFC 8707 `resource` parameter, and sends `Authorization: Bearer <token>` on every request. This page describes specification **2026-07-28**, the latest revision. Servers on stdio SHOULD NOT follow this flow and instead get credentials from the environment.

## Details

### Step by step

| # | Client action | Server response |
|---|---|---|
| 1 | MCP request without a token | MCP server: `401 Unauthorized`, `WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"`, optionally `scope="files:read"` |
| 2 | GET the `resource_metadata` URL. Without that parameter, try `/.well-known/oauth-protected-resource/<endpoint path>`, then `/.well-known/oauth-protected-resource` | MCP server: metadata with `authorization_servers` |
| 3 | Pick an authorization server, GET its metadata (`/.well-known/oauth-authorization-server`, then `/.well-known/openid-configuration`) | Authorization server: metadata. The `issuer` must equal the issuer used to build the URL |
| 4 | Check that `code_challenge_methods_supported` is present, otherwise stop | |
| 5 | Get a client ID (see below) | Authorization server |
| 6 | Browser to the authorization endpoint with `code_challenge` (`S256`), `resource`, scopes | Authorization server: user consents, redirects with a code (and `iss`) |
| 7 | Token request with `code_verifier` and `resource` | Authorization server: access token |
| 8 | MCP request with `Authorization: Bearer <token>` | MCP server: validates audience, then answers. Bad or expired token: `401`. Insufficient scope: `403` with `error="insufficient_scope"` |

### Client registration

Clients that support every option SHOULD prefer, in order: pre-registered client information, **Client ID Metadata Documents** (when the authorization server sets `client_id_metadata_document_supported`), Dynamic Client Registration (when it offers a `registration_endpoint`), then asking the user. With a Client ID Metadata Document, the `client_id` is an HTTPS URL with a path that serves a JSON document with at least `client_id`, `client_name` and `redirect_uris`. Dynamic Client Registration (RFC 7591) is **deprecated** in this revision and kept for backwards compatibility.

### Server duties

- Validate that the token was issued for this server as audience, and reject others (RFC 8707).
- Never pass the received token to an upstream API. If you call one, use a separate token from that API's authorization server.
- The `resource` value is the server's canonical URI, for example `https://mcp.example.com/mcp`, with no fragment.

### Common mistakes

- Serving no Protected Resource Metadata at all. The spec requires one of the `WWW-Authenticate` header or a well-known URI.
- Accepting any valid token from the same authorization server without an audience check.
- Forwarding the client's token to a third-party API.
- Putting the access token in the URL query string. The spec forbids it.
- Treating `scope` as fixed. Clients must treat the challenged scopes as authoritative for the current operation.
- Applying this flow to a stdio server.

## See also

- [[mcp-transports-stdio-vs-http]]
- [[mcp-streamable-http-sessions]]
- [[mcp-connection-errors]]
- [[mcp-2026-07-28-changes]]

## Sources

- [MCP Specification 2026-07-28 — Authorization](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization)
- [MCP Specification 2026-07-28 — Authorization Server Discovery](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/authorization-server-discovery)
- [MCP Specification 2026-07-28 — Client Registration](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/client-registration)
- [MCP Specification 2026-07-28 — Authorization Security Considerations](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/security-considerations)
- [RFC 9728 — OAuth 2.0 Protected Resource Metadata](https://datatracker.ietf.org/doc/html/rfc9728)
- [RFC 8707 — Resource Indicators for OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8707.html)

## Sources

- [MCP Specification 2026-07-28 — Authorization](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization)
- [MCP Specification 2026-07-28 — Authorization Server Discovery](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/authorization-server-discovery)
- [MCP Specification 2026-07-28 — Client Registration](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/client-registration)
- [MCP Specification 2026-07-28 — Authorization Security Considerations](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/security-considerations)
- [RFC 9728 — OAuth 2.0 Protected Resource Metadata](https://datatracker.ietf.org/doc/html/rfc9728)
- [RFC 8707 — Resource Indicators for OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8707.html)