-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
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
mcpscope can be requested with thatclient_id - We allow any
redirect_urito be used with thatclient_id - The
mcpscope 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.
-
OAuth is a Web Based Protocol
Not all user interfaces are web based.- Issue 952 wants a voice interface.
- Issue 1046 wants client credentials flow.
-
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.- PR 646 proposes how to enable enterprise use cases.
- PR 850 proposes more fine grained access control
- Issue 990 proposes a mechanism for the client to present an ID Token
- CHEQ (An IETF Individual Draft) proposes a format for user confirmation (see below as well)
- The future of AI agents—and why OAuth must evolve A Microsoft blog post calls for OAuth to adopt fine grained access.
-
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_statementandjwks_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
- PR 883 wants to add
-
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- Ostorlab Security Research describes custom scheme account takeover attacks
-
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.- Issue 1036 and PR 887 propose an out of band mechanism for authorization.
- CHEQ: A Protocol for Confirmation AI Agent Decisions with Human in the Loop (HITL) proposes a mechanism for asking a user for confirmation.
-
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.
-
Bearer Token Access
Besides theMcp-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.
-
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 -
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:
-
Non-breaking Change
The existing OAuth flows can be used by clients with existing servers that have deployed the current specification. -
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. TheInitializecan be extended to include client posture assertions common in enterprise scenarios. -
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. -
Simplified Client Implementation
Clients no longer need to implement OAuth flows, dynamic client registration, server discovery, or manage sensitive bearer tokens. -
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. -
Enterprise-Friendly
Enterprises can build a MCP Server on top of their existing authorization mechanisms for their resources including fine grained access control. -
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. -
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 -
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
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
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
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 URIcontent-digest- SHA-256 of request body (if present)mcp-session-id- Session identifier (after initialization)created- Signature creation timestamp
Replay Protection
- Signatures MUST include
createdtimestamp - Server MUST reject signatures older than X minutes (1-3 minutes?)
- Server MUST maintain short-term cache (X minutes) of seen
RequestIdvalues and reject non-unique values
Signature Metadata Rules
createdis REQUIREDexpiresis NOT ALLOWED (validity defined by server policy)keyidMUST 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:
typetype of interaction. Onlywebis currently definedurlURL to load on user gestureexplanationmessage to be presented to usertimeouthow 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:
- New client authentication method: HTTP Message Signatures are additive - existing OAuth flows continue to work
- New interaction request mechanism: Servers can support both old and new authorization patterns
- Extended initialization message: The
clientInfoextensions 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
Labels
Type
Projects
Status