Delegated MCP authentication
Delegated MCP authentication lets a tool call execute with the caller’s upstream permissions without forwarding the caller credential to the MCP server. It is opt-in and applies only to OAuth-enabled Streamable HTTP MCP clients.
Prerequisites
Section titled “Prerequisites”- The MCP client uses Streamable HTTP and has an authorized OAuth configuration.
- Its authorization server supports OAuth 2.0 Token Exchange.
- The OAuth token endpoint and MCP resource use HTTPS. Loopback HTTP is allowed only for local development.
- The caller supplies a short-lived subject access token no larger than 16 KiB. A non-empty value above that limit fails before token exchange and never falls back to the connection’s shared credential.
Local stdio, SSE-only, and non-OAuth clients reject delegation. Requests that do not carry a subject token continue to use the existing shared-client path.
Request flow
Section titled “Request flow”- The caller sends its token to DeepIntShield in
X-MCP-Subject-Token. - DeepIntShield sends that token only to the configured OAuth token endpoint with the RFC 8693 token-exchange grant.
- The exchange includes the exact MCP server URL as the RFC 8707
resource. - DeepIntShield initializes a Streamable HTTP MCP session with the exchanged bearer token.
- The session is isolated by MCP client, resource, and a one-way digest of the caller credential.
curl "$DEEPINTSHIELD_URL/v1/chat/completions" \ -H "Authorization: Bearer $DEEPINTSHIELD_VIRTUAL_KEY" \ -H "X-MCP-Subject-Token: $CALLER_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-5.6", "messages": [{"role": "user", "content": "Use my project tools."}] }'Credential handling
Section titled “Credential handling”The subject token is removed from generic request headers and provider
extra-header maps, recorded as [REDACTED] in header audit data, never persisted,
and never placed in an error message. It is not forwarded to the MCP server and
does not replace existing agentic authorization headers.
When canonical GAF is enabled, authorization happens before the delegated
session is acquired. The same exact-workspace decision used by /mcp,
/v1/mcp/tool/execute, and autonomous execution must return Allow; a Deny,
pending approval, workload-proof failure, or unavailable policy dependency
never falls back to the connection’s shared OAuth credential.
X-MCP-Subject-Token does not populate the GAF user or delegation fields. The
MCP authorization adapter treats the governed agent as the direct caller; the
subject token is used only afterward to obtain the upstream resource-bound
transport credential.
Token endpoint redirects are disabled. The exchanged token must be a supported bearer token and is retained only until it approaches expiry.
Session isolation and scale
Section titled “Session isolation and scale”Each process holds a bounded pool of at most 1,024 delegated sessions. A cold caller identity performs token exchange plus MCP initialization. A warm caller avoids those network operations, but every acquisition first revalidates the durable OAuth status, exact resource, expected authentication type, immutable MCP client ID, configuration generation, and current MCP-to-OAuth binding before consulting the process-local pool. A protocol mismatch, revoke, reauthorization swap, or binding change therefore denies or evicts stale warm state. Different credentials or resources cannot share a session. Streamable HTTP session IDs returned by the MCP server remain bound to that isolated client session.
Supported standards and current boundary
Section titled “Supported standards and current boundary”The implementation follows OAuth 2.0 Token Exchange (RFC 8693), OAuth 2.0 Resource Indicators (RFC 8707), and the MCP requirements for resource-bound authorization and Streamable HTTP sessions.
This release expects an explicitly configured exchange endpoint and session flow. It does not implement that revision’s automatic protected-resource metadata discovery or step-up/claims-challenge flow. Token exchange is also not available for stdio and legacy SSE transports.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Check |
|---|---|
| Delegation rejected before exchange | Confirm OAuth is authorized and transport is Streamable HTTP. |
| Oversized subject token rejected | Keep X-MCP-Subject-Token at or below 16 KiB; larger non-empty values fail closed rather than using the shared credential. |
| Token exchange rejected | Check subject-token type, client credentials, requested resource, scopes, and authorization-server policy. |
| Session repeatedly initializes | Check token lifetime, replica stickiness, and the 1,024-session process limit. |
| Tool sees the original caller token | Stop the request and inspect custom middleware; the built-in path never forwards it. |
For standard non-delegated setup, see MCP OAuth 2.1 and OAuth 2.0 and Connecting to MCP servers.