Thanks to visit codestin.com
Credit goes to github.com

Skip to content

SEP-1299: Server-Side Authorization Management with Client Session Binding #1299

@dickhardt

Description

@dickhardt

Preamble

Title: Server-Side Authorization Management with Client Session Binding
Author: @dickhardt
Status: Draft
Type: Feature
Created: 2025-08-04

Holding on creating a PR until there is community interest in this enhancement.

Abstract

This SEP proposes moving OAuth authorization flow management from MCP Clients to MCP Servers, eliminating the need for dynamic client registration and server discovery by clients. The proposal introduces two key mechanisms: (1) a proof-of-possession system for MCP Clients to prove session continuity over extended periods, and (2) a server-directed browser redirect capability that allows MCP Servers to handle authorization flows. This provides a more secure, authenticated connection between the client and the server, enables MCP servers to manage multiple authorization contexts and chain authorization requests across server hierarchies, and allows existing resource servers to use existing authorization mechanisms.

Motivation

MCP has enabled AI agents to discover and invoke arbitrary APIs, driving a dramatic shift in IT architecture. The MCP authorization specification defines how an MCP Client can obtain authorization to access protected resources at an MCP Server using OAuth. This represents a novel usage of OAuth that differs significantly from traditional patterns.

In traditional OAuth deployments, developers pre-register their applications with authorization servers that protect specific resources. Developers know in advance which scopes their applications need and which authorization servers to use. Access to sensitive resources typically requires developers to provide additional verification during a manual registration process.

MCP's dynamic discovery model inverts this pattern. MCP clients dynamically discover authorization requirements by examining WWW-Authenticate headers and fetching .well-known metadata from arbitrary servers - operations that are uncommon in traditional OAuth flows.

I created this SEP based on my past experience in security architectures, my experience with OAuth (I led the design of what became OAuth 2.0 and am working on OAuth 2.1), and personal implementation experience writing an MCP Server for the Hellō Admin APIs to enable developers to register and manage their Hellō application from their IDE or CLI. I updated our OAuth infrastructure to support the MCP requirements, and while doing that, I ended up circumventing the spirit of the MCP Authorization Specification:

  • Our registration endpoint always returns the same client_id
  • Only the mcp scope can be requested with that client_id
  • We allow any redirect_uri to be used with that client_id
  • The mcp scope only allows read, create, and additive updates to resources - no destructive operations
  • To minimize the risk of token exfiltration, we do not support refresh tokens

After discussions at the recent IETF 123 meeting in Madrid, and reviewing the auth issues in this repository, I concluded that for a number of use cases, OAuth is not a good fit between the MCP Client and MCP Server.

Problems

I've included links to related issues / PRs I came across in the repo.

  1. OAuth is a Web Based Protocol
    Not all user interfaces are web based.

  2. OAuth Scopes are Coarse Grained Access
    Many applications require fine grained access control and use a policy engine to determine what access the principal has.

  3. Dynamic Client Registration (DCR)
    DCR (RFC 7591) is not a commonly deployed OAuth pattern, and the DCR trust model of open, unauthenticated registration does not map well to widely deployed OAuth infrastructure. An OAuth client is typically registered, and the authorization server knows the identity of the client application, and the developer that registered it. Additional verification can be required for access to more sensitive scopes.

    • PR 883 wants to add software_statement
    • Issue 1032 wants add software_statement and jwks_uri
    • Issue 991 proposes using a URL-based client identifier instead of DCR.
    • Issue 582 proposes Client ID Metadata Documents as an alternative to DCR
  4. Untrusted Redirect URIs
    The use of localhost and custom schemes removes one of the protocol mechanisms of identifying the client. An HTTPS redirect URI provides some assurance to the authorization server that the authorization request came from the registered client. Security research has demonstrated practical attacks including "OAuth Account Takeover by hijacking custom schemes" where malicious applications can claim the same custom URI schemes to intercept authorization responses

  5. Single Authorization Mechanism
    The only mechanism for the MCP Server to interact directly with the user is to return a 401 response and have the MCP Client request a scope from the configured authorization server. This prevents the MCP Server from getting access tokens from more than one authorization server and requires all authorization to be represented in a single access token. There is no mechanism for downstream servers to obtain their own access tokens.

  6. Implementation Complexity
    Every MCP Client and Server developer needs to implement discovery, registration, and token management. Any potential enhancement to resolve issues needs to be implemented by all clients for interoperability to servers that may require the functionality.

    • PR 971 proposes fallback to WWW-Authenticate as deploying Protected Resource Metadata is challenging.
  7. Bearer Token Access
    Besides the Mcp-Session-Id, the access token from the authorization server is the only mechanism to bind requests across a session and maintain context, and both of these are bearer tokens. There is no trusted source of the client identity, and the user identity is abstracted by the single access token. This is a barrier to adoption in high value deployment environments.

    • Issue 544 describes this and a number of other security issues with the current design.

Proposed Solution

To move authorization management to the MCP Server, the server needs both a binding between the instance of the MCP Client and the server, and a mechanism to request the client to have an interaction with the server.

  1. Cryptographic Binding Between MCP Client and MCP Server
    When a client instance starts a relation with a server, it generates a key pair, proves possession of the private key, shares the public key with the server on first use. The client proves possession of the private on all subsequent requests. The server can now track user and session context with the public key vs an OAuth access token. HTTP Message Signatures (RFC 9421) is the proposed cryptographic binding mechanism. See Rationale for a comparison to other mechanisms

  2. Interaction Request
    At any time, the server can request the client to present a prompt for user to interact directly with the MCP Server. This interaction request can be the response to an MCP request, or sent as an event over SSE. If the interaction request is a web interaction (other interaction channels may be defined), it will contain a description and a URL. The prompt and URL are opaque to the client. The URL should contain context to bind the user interaction to the client instance. The URL may be at the MCP Server, or could be a delegate for the MCP Server. The redirect could be used for any of the following:

    • The user loads a page at the MCP Server that starts an OAuth flow to obtain an access token. The MCP Server is the OAuth client in this flow, and binds the resulting access token to the client instance.
    • Present the user a contextual description of an operation to be performed and obtain confirmation. Examples include confirmation of wiring $1M or deleting a database.
    • Log the user in with their enterprise credentials at the MCP Server so that the MCP Server or downstream resources can make policy decisions using existing access control mechanisms when future requests are made by the MCP Client to the MCP Server.

    Note the MCP Server can initiate an interaction with the user directly if it has a channel such as pushing a message to the user's mobile phone for a confirmation.

Benefits of Client Authentication and Server-Side Authorization

Having the client authenticate to the server, and moving authorization management to the MCP Server provides several advantages:

  1. Non-breaking Change
    The existing OAuth flows can be used by clients with existing servers that have deployed the current specification.

  2. Improved Client Security Posture
    Access and refresh tokens are now managed in a server and not by the client. Exfiltration of bearer tokens on a user's device is no longer a security risk. The client instance identity is verified with proof of possession. The Initialize can be extended to include client posture assertions common in enterprise scenarios.

  3. Preregistered OAuth Clients
    the MCP Server is now the OAuth client and can be preregistered with an HTTPS redirect URI and is able to manage client secrets, building on existing, deployed OAuth infrastructure.

  4. Simplified Client Implementation
    Clients no longer need to implement OAuth flows, dynamic client registration, server discovery, or manage sensitive bearer tokens.

  5. Simplified Server Implementation
    Servers can now use the access management systems that are currently in use for the resources and functionality to be made available over MCP. No requirement to deploy DCR or OAuth discovery endpoints.

  6. Enterprise-Friendly
    Enterprises can build a MCP Server on top of their existing authorization mechanisms for their resources including fine grained access control.

  7. Dynamic Authorization
    Servers can request authorization at any time, supporting step-up authentication and progressive consent bringing humans in the loop with the server for critical operations.

  8. Policy Enforcement Flexibility
    Servers making authorization decisions based on operation sensitivity, client posture, IP changes, and other contextual factors. They can now request additional authorization or authentication without losing context, rather than just returning an opaque to the user

  9. Multi-Resource Support
    Servers can manage multiple access tokens for different backend resources and chain authorization requests through server hierarchies

Protocol Comparison

Current OAuth Flow

sequenceDiagram
    participant Client as MCP Client
    participant Server as MCP Server
    participant AS as Authorization Server
    participant Browser as User Browser
    participant RS as Resource Server

    Note over Client, Server: Initial MCP Request Without Authorization

    Client->>Server: MCP request without token
    Server-->>Client: HTTP 401 Unauthorized with WWW-Authenticate header

    Note over Client, Server: Extract resource_metadata<br/>from WWW-Authenticate

    Client->>Server: GET /.well-known/oauth-protected-resource
    Server-->>Client: Resource metadata with authorization server URL

    Note over Client, AS: Validate RS metadata,<br/>build AS metadata URL
    Client->>AS: GET /.well-known/oauth-authorization-server
    AS-->>Client: Authorization server metadata
    
    Note over Client, AS: Register Instance of Client
    Client->>AS: POST /register (Dynamic Client Registration)
    AS-->>Client: Client Credentials
    
    Note over Client, Browser: OAuth 2.1 Authorization Flow
    Client->>Browser: Open Authorization URL
    Browser->>AS: Authorization Request
    AS-->>Browser: Authorization Code
    Browser-->>Client: Authorization Code
    
    Client->>AS: Exchange Code for Token
    AS-->>Client: Access Token

    Note over Client, Server: Authorized MCP Communication

    Client->>Server: MCP Request with Bearer Token

    Server->>RS: Resource Request
    RS-->>Server: Resource Response    
    Server-->>Client: MCP Response
Loading

Proposed Server-Side OAuth Flow With SSE Interaction Request

sequenceDiagram
    participant Client as MCP Client
    participant Server as MCP Server
    participant AS as Authorization Server
    participant Browser as User Browser
    participant RS as Resource Server

    Client->>Server: MCP Request w/ HTTP Signature
    Server-->>Client: Interaction Request SSE

    Client->>Server: Interaction URL

    Note over Client, Browser: OAuth 2.1 Authorization Flow
    Server-->>Browser: Open Authorization URL
    Browser->>AS: Authorization Request
    AS-->>Browser: Authorization Code
    Browser-->>Server: Authorization Code
    
    Server->>AS: Exchange Code for Token
    AS-->>Server: Access Token

    Note over Server: MCP Request can now be completed
  
    Server->>RS: Request with access token
    RS-->>Server: Resource Response
    Server-->>Client: MCP Response SSE
Loading

Proposed Server-Side OAuth Flow With Interaction Request Response

sequenceDiagram
    participant Client as MCP Client
    participant Server as MCP Server
    participant AS as Authorization Server
    participant Browser as User Browser
    participant RS as Resource Server

    Client->>Server: MCP Request w/ HTTP Signature
    Server-->>Client: Interaction Request Response
    
    Note over Client, Browser: Client presents interaction to user
    Client->>Browser: Open Interaction URL
    Browser->>Server: Load interaction page
    
    Note over Server, Browser: OAuth 2.1 Authorization Flow
    Server-->>Browser: Redirect to Authorization Server
    Browser->>AS: Authorization Request
    AS-->>Browser: Authorization Code
    Browser-->>Server: Authorization Code with session binding
    
    Server->>AS: Exchange Code for Token
    AS-->>Server: Access Token
    
    Note over Server: Authorization complete, notify client
    Server->>Client: POST to completion endpoint (id=request_id)
    
    Note over Client: Client remakes original request
    Client->>Server: MCP Request w/ HTTP Signature (retry)
    
    Note over Server: Now authorized, can complete request
    Server->>RS: Request with access token
    RS-->>Server: Resource Response
    Server-->>Client: MCP Response
Loading

Specification

HTTP Message Signing Profile

For security and interoperability, we profile HTTP Message Signing specifying how the public key is exchanged, what the keyid is, and which fields are included in the signature.

Key Management

Clients generate a public/private key pair per MCP server using Ed25519:

{
  "kty": "OKP",
  "crv": "Ed25519",
  "x": "base64url-encoded-public-key",
  "d": "base64url-encoded-private-key"
}

Rather than a self signed cert, SEP 1289 could be used.

The keyid is the JWK thumbprint per RFC 7638)

The MCP Server uses the keyid to identify the client instance.

Client Initialization

The client includes the public_key and optional callback_url in the clientInfo of the initialize request :

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    ...
    "clientInfo": {
      "public_key": {
          "kty": "OKP",
          "crv": "Ed25519",
          "x": "base64url-encoded-public-key",
      },
      "interaction_completion_uri": "http://localhost:XXXX"
    }
  }
}

See Interaction Request for details on interaction_completion_uri

Signature

Required HTTP Headers:

Signature-Input: sig1=("@method" "@target-uri" "content-digest" "mcp-request-id" "created");created=1234567890;keyid="JWK-thumbprint";alg="ed25519"
Signature: sig1=:base64-signature:
Content-Digest: sha-256=:content-hash:
MCP-Session-Id: unique-session-identifier
Required Signed Fields

Every MCP request MUST include a signature over these fields:

  • @method - HTTP method
  • @target-uri - Full request URI
  • content-digest - SHA-256 of request body (if present)
  • mcp-session-id - Session identifier (after initialization)
  • created - Signature creation timestamp
Replay Protection
  • Signatures MUST include created timestamp
  • Server MUST reject signatures older than X minutes (1-3 minutes?)
  • Server MUST maintain short-term cache (X minutes) of seen RequestId values and reject non-unique values
Signature Metadata Rules
  • created is REQUIRED
  • expires is NOT ALLOWED (validity defined by server policy)
  • keyid MUST be the JWK thumbprint
  • Field sets are FIXED by specification (no negotiation)
Algorithm Requirements
  • Primary algorithm: Ed25519 (alg="ed25519")
  • Fallback: TBD
Example Implementation
POST / HTTP/1.1
Host: server.example.com
Content-Type: application/json
Content-Digest: sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:
MCP-Session-Id: sess_abc123
Signature-Input: sig1=("@method" "@target-uri" "content-digest" "mcp-session-id" "mcp-request-id" "created");created=1234567890;keyid="JWK-thumbprint";alg="ed25519"
Signature: sig1=:LAH8BjcfcOcLojiuOBFWBo0hWDdMOGvAdEBM0h/MIRoNfj6Ae5OOKlEOUcKTOvXsyHkC5bV9D6m9QQDnR3QxDw==:

{
  "jsonrpc": "2.0",
  "id": "request_12345",
  "method": "tools/call",
  "params": {
    "name": "example_tool",
    "arguments": {}
  },
}

This approach provides backward compatibility and strong cryptographic guarantees while maintaining the simplicity and flexibility that makes MCP accessible to developers.

Interaction Request

An interaction can be requested by providing a SSE event if Content-Type is text/event-stream or an error response if Content-Type is application/json. A text/event-stream response is recommended as it allows the an interaction to be performed while a request is outstanding and a more seamless user experience.

The interaction request has the following data:

  • type type of interaction. Only web is currently defined
  • url URL to load on user gesture
  • explanation message to be presented to user
  • timeout how long the URL is valid for

text/event-stream response

event: interaction_required
data: {
  "type": "web",
  "url": "https://mcp.example.com/oauth/authorize",
  "explanation": "Example requires authorization to complete this request",
  "timeout": 300
}

application/json Response

{
  "jsonrpc": "2.0",
  "id": "request_12345",
  "error": {
    "code": -32XXX,  // predefined error
    "message": "User interaction required",
    "data": {
      "type": "web",
      "url": "https://mcp.example.com/oauth/authorize",
      "explanation": "Example requires authorization to complete this request",
      "timeout": 300
    }
  }
}

If a interaction_completion_uri was provided in the initialize message, the server will load it with the query parameter id set to the value of the RequestID. The MCP Client can then retry its request.

Rationale

Several cryptographic mechanisms could provide proof of possession for MCP client session binding. This section analyzes the trade-offs of each approach.

Mutual TLS (mTLS)

Description: Client presents a self signed certificate during TLS handshake.

Pros:

  • Transport-level security, automatic with TLS
  • Strong cryptographic guarantees
  • Well-established in enterprise environments
  • No application-layer signature computation required

Cons:

  • In cloud deployments, TLS terminates at the CDN or the load balancer, not at web application.
  • TLS is required, adding significant complexity to local development environments
  • Not all TLS implementations expose client certificates to applications

Verdict: Wrong layer for an application

Signed JSON-RPC

Description: Client signs JSON-RPC message content using JWS or similar mechanisms.

Pros:

  • Protocol-native approach
  • Message-level integrity
  • Can work over any transport

Cons:

  • No protection for HTTP headers
  • Sending JWS instead of JSON breaks backward compatibility
  • Easily replayed

Verdict: Too narrow in scope for complete session security.

HTTP Signatures (RFC 9421)

Description: Client signs HTTP requests using cryptographic signatures in HTTP headers.

Pros:

  • Application-layer security independent of transport
  • Works across all HTTP implementations
  • Request integrity and authenticity in single mechanism
  • Replay protection when combined with RequestId cache
  • Backwards compatible as older servers can ignore headers

Cons:

  • Signature computation overhead per request
  • RequestId cache to protect against all replay attacks

Verdict: Optimal balance of security and implementability for MCP.

Based on the analysis above, we propose using HTTP Message Signatures (RFC 9421) as the proof of possession mechanism for MCP.

Backward Compatibility

This SEP introduces optional changes that do not break existing implementations:

  1. New client authentication method: HTTP Message Signatures are additive - existing OAuth flows continue to work
  2. New interaction request mechanism: Servers can support both old and new authorization patterns
  3. Extended initialization message: The clientInfo extensions are optional fields

Reference Implementation

None at this time.

Security Implications

Security Improvements

This SEP addresses several critical security concerns:

1. Dynamic Client Registration Vulnerabilities

Current Risk: DCR allows unauthenticated client registration, enabling potential phishing attacks.
Mitigation: Eliminates DCR requirement by moving OAuth to server-side.

2. Bearer Token Exposure

Current Risk: Access tokens stored on client devices can be exfiltrated.
Mitigation: Tokens managed server-side, only cryptographic proof of possession on client.

3. Untrusted Redirect URIs

Current Risk: localhost and custom URI schemes reduce client identification assurance.
Mitigation: Server manages redirects with HTTPS endpoints and proper validation.

4. Session Binding Weaknesses

Current Risk: Only bearer tokens provide session continuity.
Mitigation: Cryptographic session binding with replay protection.

New Security Considerations

1. HTTP Signature Security

Risks:

  • Private key compromise allows impersonation
  • Signature timing attacks if implementation is vulnerable
  • Replay attacks if timestamp validation is insufficient

Mitigations:

  • Ed25519 provides strong cryptographic guarantees
  • Short signature validity windows (1-3 minutes)
  • Request ID caching prevents replay attacks
  • Key rotation policies recommended

2. Interaction Request Security

Risks:

  • Malicious servers could request excessive user interactions
  • URL tampering in interaction requests
  • Session fixation through interaction flows
  • Interaction URL binding attacks where malicious actors attempt to complete authorization flows for other client sessions

Mitigations:

  • Client controls interaction presentation to user
  • HTTPS required for interaction URLs
  • Session binding prevents fixation attacks
  • Timeout limits prevent indefinite authorization requests
  • Interaction URLs MUST contain cryptographically secure, unguessable session binding tokens that tie the web interaction to the specific MCP client instance. These tokens should be:
    • Cryptographically random with sufficient entropy (minimum 128 bits)
    • Unique per client session and interaction request
    • Validated by the server to ensure the web interaction corresponds to the correct MCP client binding
    • Short-lived to limit exposure window

3. Server-Side Token Management

Risks:

  • Server compromise exposes multiple user tokens
  • Token leakage through logs or debugging
  • Inadequate token storage security

Mitigations:

  • Standard OAuth token security practices apply
  • Encrypted token storage recommended
  • Audit logging for token usage
  • Token compartmentalization by user/scope

Threat Model Analysis

Threat: OAuth Client Impersonation / Phishing Attacks

  • Before: Possible through DCR registration abuse
  • After: OAuth clients are preregistered and have https redirect URIs

Threat: Token Theft

  • Before: Bearer tokens vulnerable on client devices
  • After: No tokens on client, only private keys (standard key management)

Threat: Session Hijacking

  • Before: Bearer token theft enables session takeover
  • After: Cryptographic binding prevents session hijacking

Security Recommendations

For MCP Client implementations:

  • Generate unique key pairs per server relationship
  • Implement secure key storage (OS keychain, hardware security modules)
  • Validate interaction request URLs before presenting to users
  • Implement proper signature timing to prevent side-channel attacks

For MCP Server implementations:

  • Implement proper signature verification with timing attack protection
  • Use secure random number generation for session identifiers
  • Implement rate limiting on authorization requests
  • Follow OAuth security best practices for token management
  • Log security events for audit purposes

Metadata

Metadata

Assignees

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions