Here's the thing about MCP authorization that nobody explains clearly: it's not a custom security layer that Anthropic invented. It's OAuth 2.1, applied to a specific new context, with a set of role assignments that the specification defines precisely. The confusion isn't about the technology. It's about which piece does what, and where the boundary sits between the component that issues tokens and the component that enforces them.
I've watched this confusion produce production failures in a pattern that's almost predictable by now. A team wires up an MCP server, confirms the client can connect, and calls it "authorized." Three months later someone asks why an agent can call a write tool it was never supposed to touch. The answer is usually that the token was issued correctly but nobody built the scope enforcement on the server side. Two different problems. One unbuilt solution.
The mcp authorization specification is concrete. It has distinct roles, specific RFC dependencies, and non-negotiable patterns for how tokens move. Understanding those patterns is what separates a setup that works from one that just looks like it works until it doesn't.
The part teams learn too late
- MCP authorization is OAuth 2.1 applied to AI agent contexts, not a new protocol invented for MCP.
- The authorization server and MCP server have separate, non-overlapping jobs - conflating them is where most production failures start.
- Authentication confirms identity; authorization enforces what that identity can do. The spec handles both, but through distinct mechanisms that must each be implemented.
- Enterprise SSO integration requires deliberate architectural work that goes well beyond what the base spec provides.
- "Optional at the protocol level" does not mean optional in production.
What MCP Authorization Actually Is - and What the Specification Covers
MCP authorization is the mechanism by which HTTP-based mcp clients obtain OAuth 2.1 access tokens from a dedicated authorization server and present those tokens to mcp servers that act as resource servers. That sentence has three moving parts, and each one matters.
The mcp client is the consumer: an AI agent, an IDE copilot, or an automation workflow making requests. The authorization server is a separate service that authenticates the client, collects user consent, and issues tokens. The mcp server receives those tokens on every request and validates them before allowing any tool to execute. It is the resource server in the OAuth 2.1 model.
What authorization in mcp covers: the model context protocol specification defines exactly how this token exchange happens, which flows are required, and how clients discover the authorization server in the first place. What it does not cover: what happens inside your backing APIs once the token passes validation. That gap matters and I'll come back to it.
The part most readers miss is that the specification marks authorization as optional at the protocol level, but this designation is about minimum viable connectivity between an mcp client and an mcp server in a local, trusted context. For any HTTP-based MCP server exposed to untrusted clients, the spec's own guidance is not actually optional. The optionality is a protocol-layer designation, not a production safety decision. Teams that read "optional" and skip the implementation learn this distinction from their security team later, under less favorable conditions.
![]()
Why the MCP Authorization Model Builds on OAuth 2.1 Instead of a New Protocol
The deliberate choice to build on OAuth 2.1 rather than invent a custom mechanism is worth understanding before you evaluate any MCP implementation. The mcp spec didn't need to solve identity and consent from scratch. Those problems already have solutions, and those solutions already have infrastructure behind them.
This is an architectural decision with real practical implications. If your team is already running OAuth 2.1 infrastructure, you're working from a known security surface. Your security team knows what to audit. Your IdP knows what to integrate with. You're not introducing an entirely novel attack surface to your production environment. That's a real risk reduction, not a marketing point.
Aembit's technical analysis of the MCP authorization specification documents this explicitly: the spec standardizes client access to protected resources using OAuth 2.1 with PKCE and introduces Protected Resource Metadata to decouple access control from MCP servers and align with existing identity infrastructure. The practical implication of that last phrase - "align with existing identity infrastructure" - is that teams already running OAuth authorization can connect MCP into their existing identity stack rather than building a parallel one.
The choice to leverage existing authorization patterns matters for architects evaluating risk on a timeline. You audit the implementation, not the protocol. Bugs in your MCP authorization implementation are OAuth 2.1 bugs, which have known remediation paths, documented CVEs, and a security community that will find them. A custom protocol offers none of that history.
oauth authorization in the MCP context also means the authorization code flow is the primary pattern, with PKCE required for public clients. Why that specific combination becomes clear in the next section.
Why OAuth 2.1 and PKCE Are the Right Fit for AI Agent Clients
PKCE (Proof Key for Code Exchange) exists to solve a specific problem: how do you protect an oauth 2.1 authorization code exchange when the client can't safely store a secret? A native mobile app can't store a client secret securely. Neither can a browser extension. And neither can an AI agent or IDE copilot running as a public client.
This is exactly the mcp host scenario. When an AI agent acts on behalf of a user, it's operating as a public client. Storing a client secret in an agent process that runs in user-controlled environments is not a meaningful security control. Authorization code interception is a real attack path for these clients if the exchange isn't protected.
PKCE closes that gap. The client generates a code verifier before the authorization request, sends a hash of it (the code challenge) with the request, and then proves it holds the original verifier when exchanging the authorization code for a token. An intercepted code is useless without the verifier. mcp clients and mcp servers operating in public client scenarios get meaningful authorization code protection without requiring a secret that can't actually be kept secret. That's why the spec requires it, not as a best practice recommendation but as a structural requirement for this class of client.
The RFC Dependencies Most Teams Miss Before Implementing
The MCP authorization specification doesn't stand alone. It depends on a set of RFCs that most teams don't fully inventory before building. Missing any of these in your mcp implementations produces a setup that is partially compliant and fully broken in specific edge cases.
The checklist that separates compliant implementations from broken ones, drawn from the specification's own requirements and Christian Posta's field analysis:
- OAuth 2.1 with PKCE - the core flow requirement for public clients; not optional for HTTP-based deployments
- RFC 8414 - Authorization Server Metadata - enables clients to discover authorization server endpoints automatically via a well-known URL; without this, clients require hardcoded configuration
- RFC 9728 - Protected Resource Metadata for authorization - allows the MCP server to advertise its authorization server location to clients that receive a 401; this is how clients know where to obtain tokens in the first place
- RFC 7591 - Dynamic Client Registration - enables clients to register with the authorization server programmatically; particularly important for tools and agents that can't be pre-registered manually
- RFC 8707 - Resource Indicators - allows tokens to be scoped to specific resource servers, reducing the risk that a token issued for one MCP server can be replayed against another
Teams that implement OAuth 2.1 but skip RFC 9728 end up with clients that can't discover the authorization server without manual configuration. Teams that skip RFC 7591 have a dynamic client registration gap that matters the moment you need to onboard agents programmatically at scale. The metadata for authorization server discovery in RFC 8414 is what makes the whole handshake automatable. Miss it and you've built something that works in your test environment and breaks when someone tries to connect a new client type.
How the MCP Authorization Flow Works: Roles, Tokens, and Responsibility Boundaries
The authorization flow in MCP has a specific sequence, and the role assignment at each step is the part that most teams get confused about. Let me walk through it with the boundaries made explicit, because the boundary is where most implementation mistakes live.
A client attempts to call a protected MCP server endpoint. The server returns a 401 with WWW-Authenticate headers pointing to its Protected Resource Metadata. The client fetches that metadata to discover the authorization server location. It then initiates the OAuth 2.1 authorization code flow with PKCE against that authorization server, redirecting the user to grant consent. The authorization server authenticates the user, collects consent, and returns an authorization code. The client exchanges that code (with its PKCE verifier) for an access token. On every subsequent request to the MCP server, the client presents that token in the Authorization header. The MCP server validates the token and enforces scope.
This is the authorization flow end-to-end. Two things happen at two completely different places. The authorization server handles identity and consent. The MCP server handles enforcement. These are separate responsibilities and separate implementations. Conflating them is the source of most production security failures I see described when teams report problems with MCP deployments.
What the Authorization Server Owns vs. What the MCP Server Enforces
The division of labor is precise and non-negotiable. One authorization server handles authentication, consent collection, and token issuance. The mcp server's job starts after the token exists.
The authorization server owns: verifying who the client is, confirming the user has consented to the requested scopes, issuing a signed access token with those scopes embedded, and (when applicable) issuing refresh tokens for long-running sessions. It does not know or care what the MCP server will do with the token once it receives it. That is not the authorization server's problem to solve.
The MCP server's responsibility begins at token receipt. MCP servers must validate the token on every request: verify the signature, check the issuer, confirm the audience claim matches this specific server, and enforce the scope claims against the tool being invoked. Authorization logic at the MCP server level is not a passthrough. It's an active enforcement step per request.
The common mistake: teams build the authorization server integration correctly and then assume the MCP server is "authorized" because it received a valid token. A token that is cryptographically valid but carries the wrong scopes for the requested tool should be rejected. That rejection happens at the MCP server. One authorization server can serve multiple MCP servers, but each server must define its own scope requirements and enforce them independently. You cannot define multiple authorization servers and treat scope enforcement as someone else's responsibility. It never is.
Access Token and Refresh Token Lifecycle in an MCP Context
Access tokens in MCP follow the OAuth 2.1 model: short-lived, scoped, and validated on every request. The short-lived part is not just a recommendation. Aembit's analysis of the specification documents specifically that MCP guidance explicitly forbids server-side sessions and mandates per-request token validation. This breaks a pattern that teams coming from traditional web application architecture tend to reach for instinctively.
In a session-based web app, you authenticate once and the session persists. An MCP client can't carry that assumption. Every call to the MCP server validates the access token against the authorization server. There is no "I already checked this user five minutes ago" shortcut that the spec allows. This is a deliberate design choice to reduce the risk of a compromised session giving unlimited access across a long window.
The refresh token exists for longer-running agent sessions. When an oauth token expires mid-workflow (which will happen in any agent session that runs longer than the token lifetime), the client uses a refresh token to obtain a new access token without requiring the user to re-consent interactively. Initial authorization requires user presence and consent. Subsequent token refreshes in the same session don't. This is the correct model for AI agent workflows that may run for extended periods.
A practical setup note: if you're running agent sessions that can span hours, the access token lifetime needs deliberate thought. Too short and you're refreshing constantly, adding latency and failure surface. Too long and you've undermined the blast-radius reduction the spec is designed to provide. Starting with an access token lifetime of 15-30 minutes and a refresh cycle as needed is a reasonable initial configuration - adjust based on your specific session duration requirements, not as a fixed rule.
![]()
Authentication and Authorization in MCP Are Not the Same Problem
I keep seeing these two conflated, and it produces a specific type of production failure that's particularly annoying to debug because the system appears to be working correctly from the outside.
Authentication answers: who is this mcp client? The authorization server handles this. It verifies the identity of the client and the end user, confirms credentials, and asserts that identity in the token it issues. When authentication succeeds, you know who is making the request.
Authorization answers: what is this identity permitted to do? The mcp server handles this. It takes the authenticated identity from the token, reads the scope claims, and decides whether this specific client with these specific scopes is permitted to invoke this specific mcp tool at this moment. Authorization capabilities are enforced at the server level, not the token issuance level.
The failure mode that shows up in practice: a team correctly implements authentication, verifies the client gets a valid token, and then does not implement scope enforcement at the server. The auth looks fine. The connection works. Every tool on the server is now accessible to any authenticated client, regardless of what scopes were granted. This is not an edge case. It's the most common MCP authorization gap I see described when teams report security concerns after initial deployment.
The specification handles both through distinct authorization mechanisms that must each be implemented. An mcp client that receives a token has been authenticated. What that token permits it to do depends entirely on what the MCP server enforces when it validates the token's scope and audience claims. A valid token is not a blank check. Every tool invocation needs a scope check behind it.
That's where the ticket usually starts.
🤔 Wait.
The MCP specification marks authorization as optional at the protocol level. But any HTTP-based remote mcp server exposed to untrusted clients with no authorization layer is accepting requests from anyone who can reach it. "Optional" here means the protocol will function without it. It does not mean the deployment is safe without it. Read the spec's optionality designation as a connectivity minimum, not a security baseline.
Where the MCP Authorization Specification Falls Short for Enterprise Environments
The base MCP authorization specification does what it says it does. The problem is that what it says it does is not the same thing enterprise security teams need. This is not a vendor complaint. It's an architectural gap between what the mcp specification defines and what large organizations' IAM environments actually require.
The current mcp authorization model is designed around OAuth 2.1 as a standalone mechanism. It handles the client-to-server token flow cleanly. What it doesn't define is how that flow integrates with existing enterprise identity infrastructure: Microsoft Entra, Okta, internal LDAP-backed IdPs, SAML federation, or any of the other identity systems that enterprise security teams have spent years building policy enforcement around.
The versions of the mcp authorization specification that exist today assume you're either operating a standalone authorization server or that you'll figure out the IdP integration yourself. For a 15-person startup shipping their first MCP server, that's fine. For an organization where every authentication event needs to flow through a centralized identity provider, comply with SSO policies, and generate audit events in a SIEM, the base spec gives you the transport layer and leaves the enterprise-grade policy layer as an exercise for the reader.
The mcp community is actively discussing this gap. The NSA's cybersecurity guidance on MCP explicitly warns that MCP currently lacks support for exchanging role-based access control permissions at instantiation, making it difficult to enforce or verify access boundaries between tasks in complex deployments. That's a significant gap if your mcp security posture depends on RBAC that gets resolved at runtime rather than at token issuance.
Teams planning to deploy mcp servers at enterprise scale should treat the specification as the foundation and plan additional architectural work on top of it, not as a complete solution. Spec-compliant implementation does not automatically mean enterprise-ready deployment.
Integrating Existing Identity Providers with the MCP Authorization Model
The specific gap for enterprise IAM teams is between what the spec defines (an abstract authorization server role) and what they actually operate (a concrete IdP like Entra ID or Okta with existing federation relationships, group memberships, and policy enforcement points).
The spec allows any OAuth 2.1-compliant service to act as the authorization server. In theory, Entra ID or Okta can fill that role. In practice, getting MCP clients to discover and interact correctly with enterprise IdPs requires configuration work that the spec doesn't provide guidance on, particularly around how protected resource metadata maps to IdP-specific authorization endpoints and how scopes align with enterprise role structures.
The risk of implementing mcp with a standalone authorization server rather than integrating with the existing IdP: you create a second identity silo. MCP tool access becomes governed by policies that exist outside the enterprise IAM system, managed separately, audited separately, and not enrolled in the central identity governance processes.
External authorization through third-party authorization services, or tight integration between the MCP authorization layer and existing internal IdPs, is the recommended direction for enterprise environments. Authorization management attached to a standalone MCP authorization server that nobody on the security team has visibility into is exactly the kind of shadow credential store that enterprise security teams spend time trying to eliminate. Implementing mcp correctly at enterprise scale means solving this IdP integration problem deliberately, not hoping it resolves itself.
Why Securing MCP for Non-Human Agent Identities Is a Harder Problem
The OAuth 2.1 authorization code flow assumes a human is present to authenticate and consent. AI agents and automated pipelines don't have that luxury. An agent that needs to call an MCP server at 3am in the middle of a workflow can't redirect a browser and wait for someone to click "Allow."
This is the gap that the spec leaves open. Aembit's specification analysis identifies strong agent authentication and infrastructure-asserted identity as the pattern needed to fill it. The idea: instead of requiring interactive consent for non-human agents, the infrastructure asserts identity based on verifiable attributes of the workload itself. The agent's identity comes from where it runs, not from credentials it holds and could potentially leak.
An mcp server can use specific authorization patterns for machine-to-machine flows, including OAuth 2.1 client credentials flow for non-interactive scenarios. But this requires thoughtful credential management: mcp servers act as oauth clients in this configuration, and the credentials issued for machine-to-machine access need rotation policies, scope constraints, and revocation procedures that the spec doesn't prescribe. The auth complexity for non-human identities doesn't go away with the protocol choice. It just moves somewhere else. Securing MCP for automated pipelines that can't do interactive consent is the implementation problem that teams solving the base spec have to solve again from scratch when they introduce agentic workflows.
![]()
MCP Authorization Best Practices That Actually Prevent the Common Failures
Each item below names a specific failure mode and the check or design decision that prevents it. These aren't generic security recommendations. They're grounded in what the spec requires and what breaks when teams skip steps.
Enforce per-request token validation, never session-based trust reuse
The spec mandates this. The failure mode is a team familiar with session-based web apps that caches "this client was authorized five minutes ago" and skips re-validation. When the token is revoked or expires, the MCP server keeps accepting requests until the cache clears. Validate the token on every call to the mcp server, not once at session start.
Implement scope enforcement at the tool level, not just at connection time
A token with valid authentication but missing tool-specific scopes should be rejected at the tool invocation point. The common mistake: checking that the token is valid, confirming the client connected, and then allowing any tool call. mcp servers must implement scope checks against the specific tool being invoked on every request. A read-scoped token should not be able to call a write tool, even if the connection succeeded.
Support dynamic client registration via RFC 7591
Mcp clients should support programmatic registration rather than requiring all clients to be pre-registered manually. The failure mode without this: you can't onboard new agent clients at scale without a manual configuration step per client. Allow mcp clients to register dynamically, and enforce that dynamically registered clients get appropriately constrained scopes rather than blanket access.
Require PKCE for all authorization code flows, no exceptions
Skip PKCE for a flow that looks "safe" today and you've left an authorization code interception vector open. The spec requires PKCE for public clients. Treat it as a universal requirement rather than case-by-case. Any new authorization flow added to your implementation should include PKCE by default.
Pass tokens in the Authorization header, not in the request body or query string
This is a basic transport hygiene point that gets missed more than it should. An access token in a query string appears in server logs, browser history, and referrer headers. In the header, it doesn't. Every implementation of how clients send tokens to the MCP server should check that the header is the delivery mechanism.
MCP authorization does not replace downstream API access controls
This is the most expensive misconception I see in how teams reason about their security posture after implementing MCP authorization. MCP authorization controls access to the MCP server and its tools. The backing services those tools call - your internal APIs, databases, SaaS systems - still need their own access controls. A token that authorizes a tool invocation at the MCP layer does not authorize everything that tool might do downstream. The core mcp authorization layer and downstream service authorization are independent enforcement points that must each be implemented. Teams that implement the MCP layer and declare themselves secure have a pleasant surprise waiting.
Use refresh tokens for long-running agent sessions, with rotation
Access token expiry during a multi-step agent workflow is a reliability failure that teams hit early. The correct architecture: issue a refresh token at initial authorization and use it to obtain new access tokens without interrupting the workflow. Use token rotation so each refresh invalidates the previous refresh token, limiting the blast radius of a stolen refresh token.
📊 In practice:
Per-request token validation against the authorization server is what the spec mandates - and it directly breaks the common session-based trust pattern teams import from traditional web auth. The implementation check is concrete: if your MCP server has any code path where a previously-seen client token bypasses validation because "we already checked it," that code path breaks the spec and breaks your security posture simultaneously. Remove it.
Who Uses MCP Authorization and What They Are Actually Trying to Control
Three types of teams are running into MCP authorization problems in practice, and each one is trying to control something different.
AI platform teams building tools for agents to call are primarily trying to control which mcp clients can access which tools via scopes and roles. The first mcp server they deploy usually starts without scope controls beyond "authenticated or not." The problem surfaces when they need to allow a read-only analytics agent to see tool outputs but prevent it from calling write operations. The authorization code flow with proper scope design solves this - but it requires thinking about scope taxonomy before building the server, not after. The mcp specification gives you the mechanism. You have to define the scopes worth enforcing.
Security and IAM teams are trying to centralize policy so they're not managing a separate credential store per MCP deployment. Their goal is OAuth 2.1 IdP integration: every MCP token should trace back to an identity event in the central identity provider, not a standalone authorization server. They want short-lived tokens, clear resource server audience claims in each token, and the ability to revoke access by revoking the IdP session. Broad long-lived credentials that aren't enrolled in central IAM governance are exactly what they're trying to eliminate. MCP authorization gives them the pattern. Getting it to federate with their existing IdP is the implementation work.
SaaS vendors and infrastructure providers exposing MCP servers to external customers need enterprise SSO integration and automated client configuration via authorization server location metadata. Their customers' agents need to discover the authorization server, register dynamically, and obtain appropriately scoped tokens - all without a manual onboarding step per customer. RFC 8414 and RFC 9728 are not theoretical dependencies for this use case. They're the mechanism that makes programmatic onboarding possible. Without them, every new customer is a manual configuration.
For teams building automation workflows on top of MCP-authorized servers, the same token and scope model applies inside the implementation. A workflow that listens for 401 responses from MCP servers, drives the OAuth 2.1 + PKCE exchange centrally, and issues calls with the resulting token is a cleaner pattern than wiring auth handling into every individual integration. Latenode supports this through JavaScript nodes that can handle the token exchange logic and its 5,500+ integrations with automatic OAuth for the underlying service connections - the kind of setup that turns a multi-week auth project into something that ships in an afternoon once you've modeled the flow once.
References
- WorkOS - Everything your team needs to know about MCP in 2026 - WorkOS - 25/03/2026
- Aembit - MCP, OAuth 2.1, PKCE, and the Future of AI Authorization - Aembit - 13/05/2025
- National Security Agency - Model Context Protocol (MCP): Security Design Considerations for AI-Driven Systems - 2025
- SOC Prime - Model Context Protocol: Security Risks & Mitigations - SOC Prime - 10/02/2026
- empires-security GitHub - empires-security/mcp-oauth2-aws-cognito - GitHub - 26/04/2025
- Stack Overflow Blog - Is that allowed? Authentication and authorization in Model Context Protocol - 21/01/2026
- Christian Posta’s blog - Avoiding MCP Confused Deputy With AAuth - 03/05/2026


