{
  "id": 16946773,
  "title": "OAuth for MCP: A Reference Architecture",
  "url": "https://urgent.news/2026/10/28/oauth-for-mcp-a-reference-architecture",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-28T19:39:54.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/neospeed83/oauth-for-mcp-a-reference-architecture-ll1"
  },
  "original_language": "en",
  "account": "OAuth integrations for MCP can become complex when the MCP server is expected to handle multiple roles simultaneously. This design may work for a single local demonstration, but it eliminates the trust boundaries that OAuth provides. A more effective reference architecture separates four roles: MCP client, authorization server, access token, and MCP protected resource.\n\nThe MCP client begins by contacting a server to learn its authorization configuration through metadata compliant with RFC 9728. This metadata identifies the canonical resource and supported authorization server. The client then utilizes authorization-server metadata from RFC 8414 to locate authorization and token endpoints. The current MCP specification necessitates this discovery for HTTP authorization, which is crucial when the client may encounter servers it was not preconfigured to know.\n\nThe metadata serves as input, not as automatic trust. The GET /.well-known/oauth-protected-resource HTTP/1.1 request is made to the resource server (e.g., mcp.example.com), which responds with a JSON payload containing the resource URL, authorization servers, supported scopes, and other relevant information. The access token issued by the authorization server must be valid only for the specific MCP server to which it is intended. The server must validate the issuer, audience, expiration, signature, and scope before processing any protocol requests.\n\nPublic clients should utilize the authorization code with PKCE, while confidential clients authenticate to the token endpoint using an appropriate method. The redirect URIs must be exact, and the state parameter should be used to bind the browser response. RFC 9700 outlines the current OAuth 2.0 security practices to follow these guidelines.\n\nScopes define capabilities and policy limits for resources. MCP scopes should be stable capabilities, such as calendar:read, rather than thousands of object identifiers. The MCP server combines scope with tenant, delegated subject, tool arguments, and resource ownership at execution time. In cases where an AI agent acts on behalf of a user, an exchange from RFC 8693 may be necessary, exchanging the upstream grant for a shorter token with a narrower scope, preserving the actor and delegated subject in a form that the authorization server and resource can understand.\n\nRevocation and audit are essential components of this architecture. The authorization server controls token or grant state, while the MCP server records the client and subject that triggered specific tools. For sensitive operations, step-up authentication can be requested instead of treating the original login as permanent approval. The overarching principle is to avoid creating MCP-specific credentials; instead, use OAuth roles correctly and let the authorization server issue bounded authority while each MCP server defends its own resource boundary.",
  "summary": "OAuth integrations for MCP become confusing when the MCP server is expected to be everything at once: resource server, login page, token issuer, and client registry. That design may work for one local demo, but it removes the trust boundaries OAuth is giving you basically for free. A useful reference architecture keeps four roles separate: MCP client, authorization server, access token, and MCP…",
  "key_points": [
    "MCP server handles multiple roles, risking loss of trust boundaries in OAuth integrations",
    "Four distinct roles: MCP client, authorization server, access token, and MCP protected resource",
    "Metadata from RFC 9728 and RFC 8414 guides client to authorization and token endpoints"
  ],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}