How Does Model Context Protocol Handle Authorization and Authentication?
Model context protocol (MCP) defines an authorization mechanism that enables clients to access restricted MCP servers on behalf of a resource owner. This mechanism operates at the transport layer and is for HTTP-based interactions. When implemented, MCP clients act as OAuth 2.1 clients, and protected MCP servers function as OAuth 2.1 resource servers. The system uses access tokens issued by an authorization server to control access.
MCP supports optional authorization, and when it is enabled over HTTP transports, implementations should conform to the defined protocol. However, STDIO-based transports are handled differently and rely on credentials from the environment instead of this specification. For other transports, implementers must apply protocol-specific security best practices.
The MCP authorization system is built on a subset of OAuth standards to maintain both security and simplicity. It aligns with OAuth 2.1 and related specifications like RFC8414 for authorization server metadata, RFC7591 for dynamic client registration, and RFC9728 for protected resource metadata. Additionally, draft standards for client ID metadata are also supported.
Try Obot Today
⬇️ Download the Obot open-source gateway on GitHub and begin integrating your systems with a secure, extensible MCP foundation.
Instructions in this section are adapted from Anthropic’s official MCP documentation.
1. Initial Handshake
When an MCP client attempts to access a protected server for the first time, the server responds with a 401 Unauthorized status. Along with this response, it includes a WWW-Authenticate header that provides a link to the protected resource metadata (PRM) document. This link is passed through the resource_metadata parameter, and it points the client to a predictable endpoint, such as:
WWW-Authenticate: Bearer realm="mcp",
resource_metadata="https://your-server.com/.well-known/oauth-protected-resource"
This mechanism informs the client that authorization is required and provides the entry point for the rest of the flow.
2. Protected Resource Metadata Discovery
After receiving the metadata URI, the client fetches the PRM document. This JSON document contains important information such as the resource identifier, supported authorization servers, and the list of supported scopes. For example:
This metadata enables the client to understand which authorization servers are valid for the resource and what kinds of access it can request.
3. Authorization Server Discovery
The next step is to fetch metadata from the selected authorization server. If multiple authorization servers are listed, the client chooses one and constructs a request to its metadata endpoint. This endpoint is typically compliant with either OAuth 2.0 Authorization Server Metadata or OpenID Connect Discovery.
The returned metadata includes essential endpoints such as:
These endpoints guide the client through the next phases of registration and token acquisition.
4. Client Registration
Once the client has discovered the necessary endpoints, it must ensure it is registered with the authorization server. This can be handled in two ways:
Pre-registered clients embed registration information within the application.
Dynamic client registration (DCR) allows the client to register itself by sending a request to the registration_endpoint.
If registration is successful, the server returns client credentials needed for authorization.
In environments where neither DCR nor pre-registration is available, the client must allow users to enter client credentials manually.
5. User Authorization
With registration complete, the client begins the user authorization process. It opens a browser to the authorization_endpoint, where the user logs in and grants access. Upon success, the server redirects back with an authorization code, which the client exchanges at the token_endpoint0 for an access token and optionally a refresh token:
This exchange follows the OAuth 2.1 authorization code flow with PKCE.
6. Making Authenticated Requests
With an access token in hand, the client can now send authenticated requests to the MCP server. Each request includes the token in the Authorization header:
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
The MCP server must validate the token and confirm the client has the required permissions before processing the request.
Model Context Protocol Authorization Security Best Practices
When implementing MCP authorization, it’s critical to follow security best practices to avoid common vulnerabilities and ensure correct behavior. Below are the key recommendations, grouped by concern area.
Token Handling and Validation
These practices focus on how tokens are issued, validated, scoped, and stored to prevent misuse:
Use established libraries: Avoid writing your own token validation or authorization logic. Instead, rely on mature, well-audited libraries. Custom implementations are error-prone and increase security risk unless handled by experts.
Short-lived tokens: Always prefer short-lived access tokens. This limits the time window in which a compromised token can be misused. If supported, configure your authorization server to issue tokens with brief expiration times.
Validate all tokens: Never assume a token is valid just because it is present. Always introspect or verify the token, confirm it is active, and check that its audience (aud) matches your MCP server. Reject tokens that are expired, malformed, or intended for a different resource.
Secure token storage: If you cache tokens on your server, store them in secure, encrypted storage with strict access controls. Implement cache eviction to avoid using expired or revoked tokens.
Apply least-privilege scopes: Avoid using broad or catch-all scopes. Instead, define fine-grained scopes per tool or capability, and enforce required scopes on the server per route or tool.
Check audience carefully: Never accept tokens with a generic audience like api. The audience should exactly match your MCP server’s identifier, and validation should enforce this.
Transport, Credentials, and System Boundaries
These recommendations reduce risk by limiting exposure across networks, roles, and authorization domains:
Always use HTTPS in production: In production environments, only accept traffic over HTTPS. Plain HTTP must be limited to local development scenarios.
Separate credentials for different roles: Use separate client credentials for your MCP server and any user-facing applications. Never reuse your server’s client secret for user flows, and always store secrets in a dedicated secret manager—never in source code.
Isolate realms and tenants: Unless you are explicitly supporting multi-tenant use, pin your MCP server to a single authorization realm. Reject tokens from other realms, even if issued by the same Keycloak instance.
Control dynamic client registration (DCR): If your system supports DCR, enforce controls such as trusted hosts and registration vetting. Avoid enabling unauthenticated registration, as this allows arbitrary clients to enroll with your authorization server.
Error Handling, Logging, and Session Safety
These practices prevent information leakage and misuse of auxiliary identifiers:
Protect sensitive data in logs: Do not log access tokens, authorization codes, secrets, or authorization headers. Sanitize logs and redact sensitive fields, especially in structured logging systems.
Return proper authentication challenges: When denying access with a 401 Unauthorized, include a WWW-Authenticate header with Bearer, realm, and a resource_metadata link to guide clients through the authorization process.
Avoid leaking error details: Expose only generic error messages to clients. Internally, log detailed error messages along with correlation IDs to support secure debugging without revealing sensitive implementation details.
Treat session identifiers as untrusted: Never rely on Mcp-Session-Id for authorization. Treat it as untrusted input, regenerate it when authorization context changes, and track its lifecycle securely on the server.
By following these practices, you can significantly reduce your attack surface and ensure that your MCP-based systems are secure in real-world deployments.