← Blog

MCP Server Authentication: Identity Binding at the Model Context Protocol Boundary

The Model Context Protocol lets an LLM client discover and call tools exposed by an MCP server. Authentication at the MCP boundary determines which identity issues the tool calls, which policy applies, and which record ends up in the audit log. This piece walks through the OAuth 2.1 authorization flow the MCP spec adopted, the pitfalls in shared-secret patterns, and the inspection-layer architecture that binds every MCP tool call to a verified identity.

ByParminder Singh· Founder & CEO, DeepInspect Inc.
Platform & Architecturemcpauthenticationoauthai-agent-securityai-engineering
MCP Server Authentication: Identity Binding at the Model Context Protocol Boundary

The Model Context Protocol (MCP) exposes a set of tools an LLM client can discover, list, and call over an HTTP transport. The MCP specification revised the authentication section in the June 2025 draft to require OAuth 2.1 with the Authorization Code flow plus PKCE for user-scoped MCP servers. The change moved MCP from a shared-secret model that fit a single-user local deployment to an identity-bound model that fits a multi-tenant hosted deployment.

The identity that authenticates to the MCP server determines which tool calls are authorized, which policy applies to the call, and which record ends up in the audit log. A misconfigured MCP server that treats every incoming request as a bearer-token holder loses the identity binding at the boundary, and every downstream control is operating on the wrong subject.

I want to walk through the OAuth 2.1 flow the MCP spec adopted, the shared-secret patterns that show up in early deployments, and the inspection-layer architecture that binds every MCP tool call to a verified identity.

OAuth 2.1 flow

The MCP spec adopts OAuth 2.1 for user-scoped servers. The flow runs in five stages.

The MCP client discovers the MCP server's OAuth 2.1 metadata at the well-known endpoint /.well-known/oauth-authorization-server. The metadata document lists the authorization endpoint, the token endpoint, the supported scopes, and the supported PKCE code challenge methods.

The MCP client generates a PKCE code verifier and derives the code challenge using SHA-256. The client redirects the user to the authorization endpoint with the code challenge, the requested scopes, and the client's redirect URI.

The user authenticates to the authorization server. The authorization server issues a redirect back to the MCP client with an authorization code and the state parameter.

The MCP client exchanges the authorization code plus the PKCE code verifier for an access token and, when the server supports it, a refresh token. The token endpoint returns the tokens as JSON.

The MCP client attaches the access token to every subsequent MCP request as an Authorization: Bearer <token> header. The MCP server validates the token against the authorization server, extracts the subject claim, and applies the identity to the tool-call authorization decision.

The flow is standard OAuth 2.1 with the PKCE extension. The MCP-specific pieces are the well-known endpoint discovery and the mapping of the OAuth subject to the MCP tool-call authorization.

Shared-secret pitfalls

Early MCP deployments predate the OAuth 2.1 requirement and often ship with shared-secret authentication. The shared-secret patterns have three recurring failure modes.

Static bearer token stored in configuration

The MCP client stores a long-lived bearer token in its configuration file. Every request from the MCP client carries the same token. The MCP server treats every request as originating from a single identity, which is the identity the token was issued to. Multi-user deployments that route through the same MCP client cannot distinguish between users at the MCP boundary. The audit log records a single subject, and the Article 19 identity requirement fails on the first inspection.

API key in query parameter

Some deployments pass the API key as a query parameter on the MCP request URL. The key ends up in every log along the request path: the load balancer log, the reverse-proxy access log, the browser history if a user pastes a URL, the referer header when the MCP server makes a follow-on HTTP call. The key rotation cadence has to match the log retention cadence, and the two rarely align.

Shared workspace secret across tools

A single MCP server exposes multiple tools that reach different backend systems. The MCP client authenticates once with a workspace secret. The MCP server uses the workspace secret's identity for all tool calls regardless of which tool the LLM invokes. A tool that reaches the CRM and a tool that reaches the code repository both operate under the same identity. The scope reduction the OAuth scope parameter is designed to enforce is skipped.

Identity binding at the inspection layer

The MCP spec's OAuth 2.1 requirement solves the authentication step. The authorization step (which identity is allowed to call which tool with which arguments) sits above the MCP server in the enforcement layer.

The inspection layer at the AI request boundary sees the MCP client's request before it reaches the MCP server. Four properties of the inspection layer make the identity binding durable.

Token validation before the request forwards

The inspection layer validates the OAuth access token against the authorization server. The validation confirms the token has not been revoked, the audience claim matches the MCP server, and the scope claim is sufficient for the requested tool call. The MCP server does not have to repeat the validation. The inspection layer is the single point of validation.

Subject extraction and injection

The inspection layer extracts the OAuth subject claim from the validated token and injects it as a policy input for the tool-call authorization decision. The subject travels with the request through the enforcement layer, and the audit log records the subject as the initiator.

Per-tool scope enforcement

The inspection layer maintains a mapping of MCP tool names to required OAuth scopes. A tool call to github.repo.write requires the repo scope. A tool call to salesforce.opportunity.read requires the salesforce:read scope. The mapping is enforced at the inspection layer regardless of whether the MCP server itself enforces it.

On-behalf-of tracking for agent calls

An MCP server called by an AI agent that is itself called by a human user requires the on-behalf-of pattern. The OAuth token the MCP client presents represents the agent. The inspection layer carries the human user's subject as the on_behalf_of field on the request. The audit log records both subjects: the agent as the immediate caller, and the human as the ultimate initiator.

Policy enforcement at the tool-call boundary

The authentication step establishes who is calling. The authorization step decides what the caller can do. The two steps run at different layers and have to agree on the identity.

The inspection layer runs the authorization step against a policy that lists which subjects can call which tools with which arguments. A policy rule that grants a sales analyst read access to Salesforce opportunities looks like:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

The rule enforces at three levels. The subject group has to match the caller. The tool name has to match the request. The argument scope (the account_id being read) has to match the subject's assigned accounts. A read attempt against an account the subject is not assigned to fails the rule and the request blocks.

Audit record shape

The audit record for an MCP tool call carries the four identity fields the inspection layer produces. The record maps to the JSON audit log schema the inspection layer emits for every AI decision.

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

The record is complete at the moment of decision. The auditor reading the record sees which identity called the tool, which policy rule authorized the call, and which arguments the call carried.

DeepInspect

This is exactly what DeepInspect does. DeepInspect sits inline between MCP clients and MCP servers, validates the OAuth 2.1 access token on every request, extracts the subject, applies the tool-call authorization policy, and produces a per-decision audit record.

The identity binding at the MCP boundary is preserved through the tool-call chain. The audit record carries the human subject and the agent subject when the on-behalf-of pattern applies. The policy enforcement runs at the inspection layer, not inside the MCP server, so the enforcement point stays consistent across every MCP server the deployment integrates.

Book a demo today.

Frequently asked questions

Does the MCP spec require OAuth 2.1 for all deployments?

The specification requires OAuth 2.1 with the Authorization Code flow and PKCE for user-scoped MCP servers. Server-to-server deployments that operate under a single machine identity may use OAuth client credentials or mTLS. Single-user local deployments may use a shared secret when the client and server share the same trust boundary. The multi-tenant hosted deployment is the case OAuth 2.1 with PKCE targets.

Can an MCP server delegate token validation to an external identity provider?

Yes. The MCP server can validate the access token by calling the authorization server's introspection endpoint, or by validating the JWT signature against the authorization server's JWKS endpoint. The inspection layer at the AI request boundary is the natural place for the validation because it can cache the introspection result across requests.

How does the on-behalf-of pattern interact with OAuth scopes?

The OAuth token the MCP client presents carries the scope the agent was granted. The on-behalf-of subject carries the identity of the human user. The tool-call authorization decision considers both. The policy engine can require that both the agent's scope permits the tool call AND the human user's role permits the tool call. A tool call that satisfies one and not the other blocks.

What happens when the access token expires mid-session?

The MCP client uses the OAuth refresh token to obtain a new access token. The inspection layer validates the new token on the next request. The session identity remains consistent across the refresh because the OAuth subject is stable while the token rotates. The audit log records the subject continuously across the refresh boundary.

Does the inspection layer see the tool-call arguments in cleartext?

Yes, for policy evaluation. The tool-call arguments are the input the policy engine evaluates. The audit log records the arguments as a hash by default, and the cleartext arguments are stored in a separate storage tier subject to the redaction policy that applies to the deployment. The regulator or auditor with the appropriate access reads the cleartext for reconstruction.

How does the inspection layer handle MCP servers that expose sensitive data through tool responses?

The inspection layer runs a second policy evaluation on the tool response before returning it to the MCP client. The response-side policy enforces data classification rules on the returned content, applies redaction where the policy requires, and produces a response-side audit record. The two records (request and response) are linked by the record_id and give the auditor the full trace of the tool call.