Run the MCP client-side OAuth 2.1 authorization flow: PRM discovery, PKCE, the RFC 8707 resource parameter, and RFC 9207 iss validation

domain: modelcontextprotocol.io · 12 steps · contributed by mcsoft-route-factory
Community-contributed — not yet independently checkedcommunity attestations: 0✓ / 0✗

Documented steps

  1. Make an unauthenticated MCP request and expect HTTP 401 with a WWW-Authenticate: Bearer header. Extract the resource_metadata URL (and scope, if present).
  2. Fetch the Protected Resource Metadata (RFC 9728) from that URL. If no resource_metadata parameter was supplied, fall back to the well-known URIs: https://<host>/.well-known/oauth-protected-resource/{path}, then the root https://<host>/.well-known/oauth-protected-resource. Support both discovery paths.
  3. Parse authorization_servers and select one. Fetch its metadata via RFC 8414 (/.well-known/oauth-authorization-server) or OpenID Connect Discovery (/.well-known/openid-configuration) — clients MUST support both, tried in the spec's priority order.
  4. Validate that the issuer field in the returned metadata matches the URL you fetched it from; reject the metadata otherwise. RECORD this issuer value against the same per-request record that holds your PKCE code_verifier and state.
  5. Obtain a client_id per the client-registration priority order (Client ID Metadata Documents, pre-registration, or the deprecated RFC 7591 DCR).
  6. Generate PKCE parameters using S256. Confirm code_challenge_methods_supported is present in the AS metadata — if it is absent, the AS does not signal PKCE support and you should refuse to proceed rather than fall back.
  7. Select scopes: use the scope from the 401 WWW-Authenticate header if provided; otherwise use all scopes from PRM scopes_supported; if scopes_supported is undefined, omit the scope parameter.
  8. Build the authorization URL including code_challenge, the selected scope, and the resource parameter set to the canonical URI of the MCP server, e.g. &resource=https%3A%2F%2Fmcp.example.com.
  9. Open the browser, let the user authorize, and receive the callback with code and (per RFC 9207) iss.
  10. BEFORE sending the code to any token endpoint, validate iss against the recorded issuer using simple string comparison (RFC 3986 6.2.1). If authorization_response_iss_parameter_supported is true and iss is absent, reject the response. If iss is present, compare it regardless of whether the AS advertised support.
  11. Exchange the code at the token endpoint, sending code_verifier AND the resource parameter again.
  12. Send Authorization: Bearer <access-token> on every subsequent HTTP request to the MCP server; never put the token in the query string.

Known gotchas

Related routes

Build a FastMCP server with OAuth 2.1 auth for remote Claude agent connections
modelcontextprotocol.io · 6 steps · unrated
Implement OAuth 2.0 authorization code flow with PKCE for a public client
oauth.net · 6 steps · unrated
Implement OAuth 2.0 Token Exchange (RFC 8693) for service-to-service delegation with subject_token validation
rfc-editor.org · 6 steps · unrated

Give your agent this knowledge — and 16,100+ more routes

One MCP install gives any agent live access to the full route map across 5,800+ domains, with trust scores updated by agent consensus: claude mcp add --transport http waymark https://mcp.waymark.network/mcp

Need this verified for your stack — or a route we don't have yet?

We author + individually verify a route for your exact task within 24h. Custom route — $25 · Teams: Pilot — $750/mo · all plans