How Does Authorization Work in MCP? OAuth for Agents Explained
MCP authorization is optional and applies to HTTP-based transports. When used, the MCP server acts as an OAuth 2.1 resource server and the AI client acts as an OAuth client. The server answers an unauthenticated request with a 401 that points to its metadata, the client finds the authorization server, the user signs in and consents, and the client then sends an access token on every request. The server must check that the token was issued for it. Metorial handles per-user sign-in and the second hop to upstream apps.
OAuth (Open Authorization) is the standard that lets a person grant an application limited access to their account without sharing a password. MCP authorization applies it to a new situation: an AI client asking a remote MCP server for access on a person's behalf.
Is authorization required in MCP?
No. The specification makes it optional and defines it only for HTTP-based transports. An implementation using stdio (the local standard input and output channel) should not follow it and should take credentials from the environment instead.
Who plays which role?
Three parties. The MCP server is an OAuth 2.1 resource server: it holds something protected and accepts access tokens. The MCP client, inside the AI application, is the OAuth client asking for access on behalf of a person. The authorization server signs the person in, asks for consent, and issues tokens. It can be the same service as the MCP server or a separate one.
What happens when a client connects?
The flow in the specification runs in these steps.
-
The client sends a request with no token. The server replies
401 Unauthorizedwith aWWW-Authenticateheader pointing to a metadata document.HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource", scope="files:read" -
The client reads that document (OAuth Protected Resource Metadata, RFC 9728, where RFC means Request for Comments) to learn which authorization server to use, then reads that server's own metadata.
-
The client identifies itself. The specification prefers Client ID Metadata Documents, where the client ID is an HTTPS URL pointing at a description of the client. Pre-registration is also allowed. Dynamic Client Registration is deprecated and kept for older servers.
-
The client sends the user to the authorization server with a PKCE challenge (Proof Key for Code Exchange, which stops a stolen authorization code from being redeemed) and a
resourceparameter naming the MCP server. -
The person signs in and approves, and the client exchanges the code for an access token.
-
The client sends
Authorization: Bearer <token>on every request, never in the URL query string.
How do tokens stay narrow?
The resource parameter, from RFC 8707 (Resource Indicators), ties the token to one MCP server. The server must check that a token was issued specifically for it, and must not accept tokens meant for anything else.
Scopes limit what the token can do. The server can state the scope it needs in the 401. If a later call needs more, it returns 403 with insufficient_scope, and the client can ask the user for a step up. The security guidance warns against publishing every possible scope up front, because a stolen broad token reaches far more.
What about the second hop?
The token a client sends to an MCP server is only for that server. If the server then calls Slack, Salesforce, or Google, it needs its own credential for that service. The specification explicitly forbids token passthrough, meaning forwarding the client's token downstream, because it defeats audience checks and muddies audit trails.
This second hop is where most teams end up with shared API keys, and it is the part the protocol leaves to you. Are MCP servers secure? covers the credential risks.
What mistakes do teams make?
The specification's own security guidance lists the common ones. Servers publish every possible scope, or use catch-all scopes such as * or full-access, so a leaked token reaches everything. Servers accept tokens without checking the audience, which is how token passthrough starts. Proxy servers that sit in front of a third-party API skip a per-client consent screen, which opens a confused deputy attack where an attacker's client rides on a user's earlier consent.
The mistake outside the specification is simpler: skipping OAuth and pasting one shared API key into a config file because it works today.
What does it look like in Metorial?
Metorial covers both hops. For the first, Magic MCP is a single URL that works with MCP-compatible clients, and you sign in through OAuth with the login you already use, so every call runs as you and reaches only the tools you are allowed.
For the second, each person connects their own account to an integration, and Metorial stores and uses the resulting tokens. Admins who want control over the OAuth app can create custom OAuth credentials: enter your own client ID and secret, add the redirect URI Metorial shows to your OAuth app, and review the scopes before saving.
Frequently asked questions
Is authorization required in MCP?
No. The specification makes it optional. When a server uses an HTTP-based transport and wants authorization, it should follow the specification. A server using the local stdio transport should instead get credentials from its environment.
Which OAuth version does MCP use?
OAuth 2.1, which is an IETF (Internet Engineering Task Force) draft that tightens OAuth 2.0, together with several related standards for discovery, resource indicators, and client registration. The specification lists the exact set.
What is token passthrough, and why is it forbidden?
Token passthrough is when an MCP server accepts a token that was not issued for it and forwards it to another API. The specification forbids it because it bypasses audience checks, breaks audit trails, and can make the server a confused deputy.
How does an MCP server get access to my Slack or Google data?
That is a second, separate authorization. The token the client sends to the MCP server is for the MCP server only. To call Slack or Google, the server needs its own credential for that service, ideally one the same user granted.
How do I handle sign-in for many people and many servers?
Put a gateway or control plane in front. It runs the sign-in once per person, stores and refreshes the upstream tokens, and applies access rules, instead of each server and each client handling it separately.