MCP Authentication¶
Category: concept Last updated: 2026-04-04 Status: draft
Summary¶
The Model Context Protocol (MCP) includes an OAuth 2.1-based authorization framework that allows AI clients to send authenticated requests to MCP servers on behalf of signed-in users. When MCP servers access sensitive resources or need to identify callers, implementing authentication via an identity provider like Microsoft Entra ID becomes necessary. Python's FastMCP library provides first-class support for this pattern.
Details¶
What is MCP?¶
The Model Context Protocol is a standardized protocol for AI agents to invoke external tools. MCP servers expose tools and resources; MCP clients (e.g., VS Code, Claude Desktop) discover and call them. When tools need to know who is calling — for per-user data, access control, or downstream API calls — authentication is required.
OAuth 2.1 Model¶
MCP authentication maps cleanly onto OAuth 2.1 roles:
| OAuth Role | MCP Role |
|---|---|
| OAuth client | MCP client (e.g., VS Code) |
| Resource server | MCP server |
| Resource owner | Signed-in user |
| Authorization server | Identity provider (e.g., Microsoft Entra ID) |
The MCP client obtains a Bearer token from the authorization server and presents it to the MCP server with each request. The server validates the token using the provider's public keys — no client secret needed at validation time.
Client Registration Options¶
Three approaches exist for authorization servers to recognize MCP clients:
- Pre-registration — The server pre-registers known client IDs. Simplest, but requires advance setup.
- CIMD (Client Identity Metadata Document) — Clients publish a JSON document describing their attributes; the server fetches and trusts it.
- DCR (Dynamic Client Registration) — Clients register themselves at discovery time, receiving a new client ID.
VS Code supports all three. Microsoft Entra ID only supports pre-registration, making it the only viable option for Entra-backed MCP servers. — [source: building-mcp-servers-entra-id.md]
Entra App Registration¶
To enable Entra authentication for an MCP server, you register an Entra application and configure:
- Delegated scope (
user_impersonation) — Signals the client acts as the user, not itself. - Pre-authorized client — VS Code's application ID is pre-authorized for the scope, eliminating per-user consent prompts.
- Admin consent for downstream APIs — If the server calls Microsoft Graph on behalf of users (via OBO flow), an admin grants consent upfront.
The registration can be scripted via the Microsoft Graph SDK (auth_init.py).
Credential Management¶
Different environments call for different credential strategies:
- Local development: Client secrets — simple, low overhead.
- Production on Azure Container Apps: Managed Identity as Federated Identity Credential (MI-as-FIC) — no secret to manage; identity is bound to the compute resource.
FastMCP Server Implementation¶
FastMCP (Python) provides a RemoteAuthProvider abstraction. The server is configured with an Azure JWT verifier that fetches Entra's public keys at startup and validates tokens on each request. No client secret is needed for validation.
Custom middleware extracts the oid (object identifier) claim from validated tokens and stores it in request state, making the user's Entra identity available to all downstream tools.
# Conceptual structure (from article)
# - RemoteAuthProvider + AzureJWTVerifier handle token validation
# - Middleware extracts "oid" claim → request.state.user_id
# - Tools read request.state.user_id for per-user operations
FastMCP 3.0 adds per-tool authorization declarations. Validation runs at both tool enumeration and invocation time — clients cannot even see unauthorized tools.
On-Behalf-Of (OBO) Flow¶
When an MCP tool needs to call a downstream API (e.g., Microsoft Graph) as the signed-in user, it exchanges the inbound MCP Bearer token for a Graph-scoped token using the MSAL SDK's on-behalf-of flow:
This enables operations like checking Entra group membership to enforce access controls. The production version uses MI-as-FIC for the assertion credential rather than a client secret.
Key Claims & Data Points¶
- MCP spec includes OAuth 2.1 authorization; MCP client = OAuth client, server = resource server — [source: building-mcp-servers-entra-id.md]
- Entra only supports pre-registration (not CIMD or DCR), constraining client authorization architecture — [source: building-mcp-servers-entra-id.md]
user_impersonationscope signals delegated (user-context) access vs. app-only access — [source: building-mcp-servers-entra-id.md]- FastMCP's
RemoteAuthProvider+ Azure JWT verifier validates tokens via public keys without server-side secrets — [source: building-mcp-servers-entra-id.md] - Managed Identity as FIC eliminates secret rotation risk in production — [source: building-mcp-servers-entra-id.md]
- FastMCP 3.0 supports per-tool authorization that runs at list time and call time — [source: building-mcp-servers-entra-id.md]
Open Questions¶
- How does MCP authentication compare to tool-calling auth in other protocols (e.g., OpenAPI/tool-use with API keys)?
- Is pre-registration the only viable option for Entra permanently, or is DCR support planned?
- How do you handle token refresh in long-running MCP sessions — does FastMCP manage this automatically?
- What happens when the OBO exchange fails mid-session (token expiry, revoked consent) — how does the server signal this to the MCP client?
- Are there performance implications of per-request JWT verification at scale?
Related Articles¶
- concepts/prompt-injection — MCP servers that access sensitive data are prime lethal-trifecta targets; authentication reduces but does not eliminate this risk
- concepts/agentic-engineering — MCP is the tool-invocation protocol underlying many agentic systems
- entities/pamela-fox — Author of the source article
Sources¶
- Building MCP servers with Entra ID and pre-authorized clients — Pamela Fox's guide to OAuth 2.1 MCP auth with Python FastMCP, Microsoft Entra, and VS Code pre-registration