SSOGEN / Learn / MCP Authentication: What the Specification Requires

Learn

MCP Authentication: What the Specification Requires

A protected MCP server acts as an OAuth resource server, answers an unauthenticated request with a 401 pointing to its metadata, and accepts only tokens issued for it.

Updated

MCP authentication flow: a client calls a protected MCP server, gets a 401 with metadata and obtains a token to retry
The spec reuses OAuth rather than inventing a new scheme.

MCP authentication is how a client proves it may call a protected server in the Model Context Protocol. It is built on OAuth:

  • Resource server. The MCP server.
  • OAuth client. The client.
  • Authorization server. A separate server that issues the tokens.

This page follows the authorization section of the specification, revision 2026-07-28, which was current when we read it.

Check the revision you build against.

When authorization applies at all

Authorization is optional in MCP, and the transport decides whether it applies:

  • HTTP-based transport. A transport that supports authorization should follow the specification.
  • Stdio. A stdio server should not; it takes credentials from its environment.

In practice, “MCP authentication” means HTTP servers you expose to more than one trusted user.

The specification builds on an IETF draft, OAuth 2.1 (draft-ietf-oauth-v2-1-13), plus several published RFCs. Because OAuth 2.1 is still a draft, some products describe their own behavior as OAuth 2.0 with extensions.

The flow, step by step

Step Who What happens Standard
1 Client Calls the MCP server with no token
2 Server Replies 401 with a WWW-Authenticate header naming its metadata URL in resource_metadata RFC 9728, section 5.1
3 Client Fetches that metadata and reads authorization_servers RFC 9728
4 Client Fetches the authorization server’s metadata RFC 8414 or OpenID Connect Discovery
5 Client Gets a client ID (a metadata document URL, pre-registration or dynamic registration) Client ID Metadata Documents, RFC 7591
6 Client Starts authorization with PKCE and a resource parameter naming the server PKCE, RFC 8707
7 Person Signs in and approves
8 Client Exchanges the code for a token, again sending resource
9 Client Sends Authorization: Bearer <token> on every request RFC 6750
10 Server Checks the token was issued for this server, then runs the tool

An annotated 401 and metadata document

This is a server’s answer at step 2, with fictional values (Acme Corp).

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.acme.example/.well-known/oauth-protected-resource",
scope="invoices:read"
  • resource_metadata. Tells the client where to look next.
  • scope. The server’s guidance for the current operation. Servers should include it, and clients treat it as authoritative for that request.

The metadata document the URL returns:

{
"resource": "https://mcp.acme.example",
"authorization_servers": ["https://login.acme.example"],
"scopes_supported": ["invoices:read", "invoices:write"],
"bearer_methods_supported": ["header"]
}
  • resource must match. It must match the identifier the metadata URL was built from, as RFC 9728 requires. This prevents anyone from feeding a client another server’s metadata.
  • authorization_servers. The document must include it with at least one entry.

A server that can’t send the WWW-Authenticate hint may publish the document at /.well-known/oauth-protected-resource instead, at the root or at the path of the MCP endpoint.

What an MCP server must do

  • Publish metadata. Publish Protected Resource Metadata so clients can find the authorization server.
  • Return 401. Return 401 for a missing, invalid or expired token.
  • Check the audience. Check that each token was issued for this server as its audience.
  • Accept only its own tokens. Accept only tokens meant for its own resources. Never accept or pass on any other token.
  • Return 403. Return 403 with error="insufficient_scope" and the needed scope when a valid token lacks permission for the operation, so the client can ask for more.
  • Header only. Never read the token from the URL query string. The client sends it in the Authorization header on every HTTP request.

The authorization server must offer metadata through RFC 8414 or OpenID Connect Discovery.

It must advertise PKCE in code_challenge_methods_supported. If that field is missing, the client must stop.

Common mistakes

Mistake Why it hurts Fix
No audience check A token issued for another service works here Verify the audience against your resource identifier on every request
Token passthrough The server forwards the client’s token to an upstream API, so the upstream cannot tell who really called Use a separate token issued to the server for the upstream API
403 where 401 belongs (or the reverse) Clients do not know whether to re-authenticate or ask for more scope 401 for no or bad token, 403 for insufficient scope
Metadata resource does not match the URL Clients reject it Make the identifier exact, including path
No PKCE advertised Compliant clients refuse to connect Publish code_challenge_methods_supported
One broad scope for every tool A single grant opens everything Define scopes per tool or group of tools
Checking only at session start Later calls run unchecked Validate on every request

The specification’s security section also covers redirect URIs (exact match, localhost or HTTPS), short-lived access tokens and token theft. Read it with the authorization section, not after.

What a scope can and cannot do

  • What a scope does. A scope decides whether a tool may be called; it does not inspect what the call contains.
  • What it does not do. An agent with the approve_invoice scope can approve any invoice the server allows, so enforce limits on amounts and records in the server as well.

How the SSOGEN MCP Gateway handles authentication

SSOGEN’s MCP Gateway sits in front of your MCP server and checks each tool call.

  • No token. A request without a token gets 401 with a WWW-Authenticate header carrying resource_metadata.
  • Metadata. Its protected-resource metadata lists the SSOGEN sign-in server in authorization_servers and the scopes in scopes_supported.
  • Scope mapping. You map scopes to the exact tool names your server advertises.
  • Out-of-scope calls. A call to a tool outside the agent’s scopes gets 403 with insufficient_scope.

SSOGEN is stricter than the baseline in two places:

  1. It accepts only tokens bound to the agent’s key through DPoP, sent as Authorization: DPoP with a proof on every request. It refuses Bearer tokens, so a client that can’t send DPoP proofs can’t connect.
  2. An administrator registers every agent in advance, in place of dynamic client registration.
  • No token forwarding. The Gateway doesn’t forward the agent’s token to your server; it passes identity headers instead.
  • Minimal reading. It reads only the method and tool name, never the arguments.

MCP Gateway explains the checks, and the Oracle EBS MCP guide covers setup.

Questions people ask

What is MCP authentication?

It’s the OAuth-based way an MCP client proves it may call a protected MCP server, using a token an authorization server issued for that server.

Does MCP require OAuth?

Authorization is optional. If an HTTP-based server supports it, follow the specification’s OAuth-based flow. Stdio servers should read credentials from the environment.

How does a client find the authorization server?

From the server’s Protected Resource Metadata document, found through the resource_metadata value in the 401 response or a well-known URL.

Can an MCP server pass the client’s token to another API?

No. The specification forbids it. The server must get its own token for the upstream API.

Where to go next

Sources, all read 2026-10-09: MCP specification, Authorization (2026-07-28), RFC 9728, RFC 8707.