MCP Authentication and Authorization: OAuth 2.1, Token Delegation, and the Confused Deputy Problem

MCP Security OAuth 2.1 Authentication AI Security

Authentication is the gatekeeper that determines whether an MCP server’s powerful capabilities are available to legitimate users or to attackers. Get it wrong, and every other security control becomes irrelevant — an unauthenticated or poorly authenticated MCP server with access to email, files, and databases is a critical vulnerability regardless of how well you’ve hardened everything else.

The OWASP GenAI Security Project’s guide identifies authentication and authorization as one of the eight core security domains for MCP servers, with specific requirements that go beyond what most developers implement by default. This post explains why those requirements exist and how to implement them correctly.

The Authentication Challenge in MCP

MCP servers face a more complex authentication landscape than traditional services because they mediate between multiple principals:

  • The user whose instructions drive the AI assistant
  • The AI model that interprets instructions and calls tools
  • The MCP client (the application hosting the AI)
  • The MCP server that executes tool calls
  • Downstream services the MCP server calls on the user’s behalf

Each of these relationships requires its own authentication and authorization controls. A weakness in any link can be exploited to bypass the others.

Mandatory: OAuth 2.1 and OIDC for Remote Servers

For remote MCP servers — those accessed over a network rather than through local STDIO or Unix sockets — the OWASP GenAI guide is unambiguous: OAuth 2.1 with OIDC is mandatory, not optional.

This requirement exists because:

OAuth 2.1 provides explicit scope control. Every access token declares exactly which resources and actions it authorizes. An MCP server can verify at tool invocation time that the token presented has the specific scope needed for that action — not just that the user is authenticated, but that they’re authorized for this specific operation.

OIDC provides cryptographic identity. OpenID Connect adds identity assertions (the ID token) that the MCP server can verify without round-tripping to the identity provider. The server validates the iss (issuer), aud (audience), exp (expiry), and signature on every request.

OAuth 2.1 tokens are short-lived by design. The modern OAuth specification (which consolidates and supersedes OAuth 2.0 best practices) emphasizes short-lived access tokens that must be regularly refreshed. This limits the damage window if a token is compromised.

What to Validate on Every Request

Don’t validate tokens only at session establishment. Validate on every tool invocation:

def validate_token(token: str, required_scope: str) -> TokenClaims:
    claims = jwt.decode(
        token,
        key=get_public_key(claims_preview['kid']),
        algorithms=["RS256", "ES256"]
    )

    assert claims['iss'] == EXPECTED_ISSUER
    assert EXPECTED_AUDIENCE in claims['aud']
    assert claims['exp'] > time.time()
    assert required_scope in claims['scope'].split()

    return claims

Never cache validation results across requests. A token that was valid at session start may be revoked mid-session.

Dynamic Client Environments

In environments where MCP clients change frequently (e.g., different AI assistants connecting to the same server), static API keys or pre-shared secrets are insufficient. Use dynamic client registration with OAuth 2.1 or OIDC to verify client identity at connection time. Allowlists, hardcoded connection policies, or mutual TLS (mTLS) are appropriate for known static relationships between specific clients and servers.

Logo

Ready to grow your business?

Start your free trial today and see results within days.

The Confused Deputy Problem

Understanding the Attack

The Confused Deputy is a classic authorization vulnerability with a particularly dangerous manifestation in MCP architectures. The attack exploits the ambiguity of whose authority an MCP server is acting with.

Consider this scenario:

  • User Alice is authenticated to an MCP server with limited permissions — she can read her own files but not others'
  • The MCP server has broad service account permissions to read all files in the organization
  • The MCP server uses token passthrough: it forwards Alice’s token to downstream services

When Alice asks the AI assistant to “summarize my project folder,” the server uses Alice’s token to access her files — correct behavior. But if an attacker tricks the server into making a request using its own service credentials (perhaps through a tool poisoning attack or indirect prompt injection), the server’s elevated permissions are used to access files Alice is not authorized to see.

The server is the “confused deputy” — it has been tricked into using its authority on behalf of someone who doesn’t have that authority, acting as a proxy for privilege escalation.

Why Token Passthrough Creates This Vulnerability

Many MCP implementations forward the client’s token to downstream APIs for simplicity. This seems intuitive — the user’s token represents the user’s permissions, so using it for all downstream calls maintains correct access control.

The problem: downstream APIs that recognize the MCP server as a trusted intermediary may grant requests using the server’s identity level, not the forwarded user token’s level. And if the MCP server ever acts on its own initiative — through AI decision-making that the user didn’t explicitly request — it may use its own credentials rather than the user’s token.

Forwarding user tokens also:

  • Breaks audit trails (downstream logs show user identity, not server identity, obscuring the MCP layer)
  • Gives an attacker who compromises the MCP server access to all forwarded user tokens
  • Creates compliance problems if tokens for different users can be confused or replayed

The Fix: Explicit Token Delegation with On-Behalf-Of Flows

Instead of forwarding client tokens, the MCP server should obtain its own tokens for downstream service access using OAuth’s On-Behalf-Of (OBO) flow:

User authenticates to MCP client → client gets user access token
MCP client presents user token to MCP server
MCP server exchanges user token for a server token via OBO flow:
  POST /token
  grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
  assertion=<user_access_token>
  scope=<minimum_required_scope>
MCP server uses its own OBO token for downstream calls

The OBO token:

  • Is explicitly scoped to the minimum permissions needed for the specific tool call
  • Identifies the MCP server as the calling party (with the user as the subject)
  • Is tied to the user’s authentication event (can be revoked when the user’s session ends)
  • Doesn’t expose the user’s full token to downstream services

Short-Lived, Scoped Tokens

The OWASP GenAI guide makes a specific recommendation: issue access tokens with lifetimes measured in minutes, not hours. This applies to both the tokens the MCP server accepts from clients and the tokens it obtains for downstream service access.

Why Short Lifetimes Matter

A stolen access token is valid for its full lifetime regardless of whether the legitimate user has logged out, changed their password, or revoked their session. A 24-hour token stolen at the beginning of a session gives an attacker 24 hours of persistent access. A 5-minute token stolen mid-session gives at most 5 minutes.

Short-lived tokens also enforce regular re-authentication events, which provide opportunities to:

  • Re-check whether the user’s account has been suspended or their permissions changed
  • Detect anomalous authentication patterns (unusual times, locations, or frequency)
  • Apply step-up authentication for sensitive operations

Token Scope Minimization

Each token should carry only the scopes needed for the specific operation being performed. Don’t issue a token with read:files write:files delete:files scope when the current tool call only needs read:files. This limits the damage if the token is intercepted or the model is manipulated into unexpected tool calls.

def get_tool_token(user_id: str, tool_name: str) -> str:
    # Map tool to minimum required scopes
    required_scopes = TOOL_SCOPE_MAP[tool_name]

    return oauth_client.get_token(
        subject=user_id,
        scopes=required_scopes,
        lifetime_seconds=300  # 5 minute lifetime
    )

Treating Sessions as State, Not Identity

A common mistake is using session IDs as authorization proxies: if a request carries a valid session ID, the server assumes it’s authorized. This conflates state management with identity verification.

The correct model: session IDs manage conversational state. Authorization is verified independently on every request by validating the OAuth token’s claims. Even a request carrying a valid session ID must present a valid, unexpired, properly-scoped OAuth token before any tool invocation is permitted.

This matters because session IDs can be stolen, guessed, or replayed in ways that OAuth tokens — which carry cryptographic integrity guarantees — cannot.

Centralized Policy Enforcement

Rather than implementing authorization checks scattered throughout individual tool handlers, the OWASP GenAI guide recommends a centralized policy gateway that:

  • Intercepts all tool invocation requests before they reach tool-specific code
  • Validates authentication (token signature, issuer, audience, expiry)
  • Enforces authorization (required scope for this specific tool)
  • Applies consent verification (has the user explicitly authorized this type of action?)
  • Implements tool filtering (is this tool allowed in this deployment context?)
  • Logs all decisions with full context for audit

Centralization ensures policies are consistently applied across all tools and agents. A tool-specific authorization check can be forgotten or bypassed during development; a gateway check cannot.

Summary: The Authentication Checklist

For remote MCP servers, the minimum authentication security bar is:

  • OAuth 2.1 / OIDC enforced for all connections
  • Token signature, issuer, audience, and expiry validated on every tool invocation
  • No token passthrough to downstream APIs — use OBO or server-issued tokens
  • Access tokens scoped to minimum required permissions per tool
  • Token lifetimes measured in minutes with mandatory refresh
  • Session IDs not used as authorization proxies
  • Centralized policy enforcement gateway in place
  • All authentication events and authorization decisions logged immutably

Frequently asked questions

Why does MCP require OAuth 2.1 rather than simpler authentication methods?

OAuth 2.1 is required for remote MCP servers because it provides delegated authorization with explicit scope control, short-lived tokens, cryptographic verification, and standardized identity assertions (via OIDC). Simpler methods like API keys or session cookies lack the scope granularity needed to implement least-privilege access, don't provide cryptographic identity guarantees, and are difficult to revoke granularly when a session ends.

What is the Confused Deputy problem in MCP?

The Confused Deputy is a privilege escalation attack where the MCP server is tricked into using its own (higher) privileges to perform actions that the requesting user is not authorized to perform. It occurs when token passthrough is used — the server forwards a user's token to downstream APIs, which may grant the user access they shouldn't have based on the server's trusted status. The fix is to use On-Behalf-Of token flows where tokens are explicitly issued for the MCP server's specific access scope.

What is token passthrough and why is it dangerous in MCP?

Token passthrough means the MCP server forwards the client's authentication token directly to downstream APIs, rather than using its own server-issued credentials. This is dangerous because: (1) it breaks audit trails — downstream systems see the user token, not the MCP server, making it impossible to attribute actions to the server; (2) it bypasses the MCP server's own access policies; (3) it creates a Confused Deputy vulnerability if the downstream API trusts the MCP server's identity more than the user's; and (4) if the MCP server is compromised, the attacker gains access to forwarded user tokens for all connected downstream services.

How short should MCP access tokens be?

The OWASP GenAI guide recommends tokens with lifetimes measured in minutes, not hours or days. Shorter token lifetimes limit the window of exploitation if a token is stolen or a session is hijacked. Every tool invocation should revalidate the token's signature, audience, and expiry — not rely on cached validation from session start.

Arshia is an AI Workflow Engineer at FlowHunt. With a background in computer science and a passion for AI, he specializes in creating efficient workflows that integrate AI tools into everyday tasks, enhancing productivity and creativity.

Arshia Kahani
Arshia Kahani
AI Workflow Engineer

Is Your MCP Authentication Architecture Secure?

Our security team assesses MCP authentication configurations, token handling, and authorization flows against the OWASP GenAI standards. Identify gaps before attackers do.

Learn more

Authenticator App MCP Server
Authenticator App MCP Server

Authenticator App MCP Server

The Authenticator App MCP Server enables AI agents to securely access 2FA codes and passwords, streamlining automated login processes and credential management ...

4 min read
MCP Security +5
Auth0 MCP Server Integration
Auth0 MCP Server Integration

Auth0 MCP Server Integration

The Auth0 MCP Server bridges AI assistants with Auth0's authentication and identity services. Integrate real-time user authentication, authorization, and identi...

3 min read
AI Identity +4