An MCP authentication failure is easier to fix when you identify where it occurs: discovering the authorization service, registering the client, redeeming a code, validating a token, or authorizing a tool action. Begin with the HTTP status, the WWW-Authenticate challenge, and a redacted request record. Repeatedly logging in will not fix a token issued for the wrong resource.
This guide uses the MCP 2026-07-28 HTTP authorization model. For the complete sequence, read MCP OAuth 2.1 and PKCE explained. For boundaries beyond authentication, use the MCP server security checklist.
Identify the failing boundary
| Observation | First check | Corrective action to investigate |
|---|---|---|
401 with no credential sent |
Did the client discover the resource and start authorization? | Inspect the Bearer challenge and metadata discovery |
401 with invalid_token |
Expiry, trusted issuer, intended audience, and validation method | Obtain a token for the correct resource; investigate validation evidence |
403 with insufficient_scope |
Does the token cover this operation? | Request the indicated scope through the authorized consent flow |
403 without a scope challenge |
Origin policy, gateway rules, or tool-level policy | Find which component denied the request before changing OAuth settings |
| Registration fails before a token exists | Client registration mechanism and redirect URI | Check pre-registration, advertised CIMD support, or the DCR compatibility path |
| Callback rejected before token exchange | Recorded issuer, response iss, and advertised support |
Correct the selected issuer or metadata; retain strict validation |
Bearer token errors distinguish invalid credentials from insufficient scope. A gateway can also deny a request before the MCP server sees it, so the status alone is not a diagnosis. RFC 6750 error semantics.
Reproduce the HTTP cases locally
Download the local authorization lab, inspect it, and run it with Node.js 18 or later. It uses built-in modules, binds only to 127.0.0.1, and reads no credentials. Its public token labels select synthetic outcomes; they are not access tokens.
node mcp-authorization-lab.cjs --self-test
The self-test prints PASS 21 checks after exercising HTTP failure and success cases, metadata, query validation, and issuer comparison. Start the interactive fixture in one terminal:
node mcp-authorization-lab.cjs --port 8765
In another terminal, request the resource without a token:
curl --include 'http://127.0.0.1:8765/mcp'
The relevant response fields are:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="http://127.0.0.1:8765/.well-known/oauth-protected-resource", scope="files:read"
The fixture deliberately uses GET and synthetic JSON results. It does not implement MCP JSON-RPC, an authorization server, PKCE exchange, or cryptographic token validation. Successful fixture responses perform no tool action. Local HTTP here is for the loopback demonstration; remote authorization endpoints need HTTPS. MCP communication security.
Missing or invalid token
Check whether the client sends an Authorization: Bearer header to the intended resource. Never put a real token in the URL, a shared terminal transcript, or an issue report. Avoid commands that print request headers when troubleshooting with real credentials.
With these public fixture labels, reproduce each invalid-token case:
curl --include --header 'Authorization: Bearer demo-expired' \
'http://127.0.0.1:8765/mcp'
curl --include --header 'Authorization: Bearer demo-wrong-audience' \
'http://127.0.0.1:8765/mcp'
curl --include --header 'Authorization: Bearer demo-wrong-issuer' \
'http://127.0.0.1:8765/mcp'
Each case produces 401 with error="invalid_token". The generic response avoids exposing the validation detail to the caller. In a real deployment, distinguish the cause through redacted server-side evidence.
For an audience failure, compare the resource identifier, the resource parameter used when obtaining the token, and the audience accepted by the resource server. A valid signature from your identity provider is insufficient when the token targets a different service. RFC 8707 resource indicators.
For an expiry failure, obtain a fresh token through the supported flow and inspect clock configuration if fresh tokens fail immediately. For signed tokens, use validated claims; merely decoding a JWT payload does not establish that its contents are authentic. For opaque tokens, use the authorization server's supported validation mechanism.
Insufficient scope
The read-only fixture token cannot perform the simulated write operation:
curl --include --header 'Authorization: Bearer demo-read' \
'http://127.0.0.1:8765/mcp?operation=write'
Inspect the challenge for error="insufficient_scope" and scope="files:write". Retrying the same token cannot expand its permission. In a user-delegated flow, request the required additional scope through authorization, preserving previously requested scopes and limiting retries. Scope escalation remains subject to policy and consent. MCP step-up authorization.
Verify the fixture's allowed case separately:
curl --include --header 'Authorization: Bearer demo-write' \
'http://127.0.0.1:8765/mcp?operation=write'
This produces 200 and a JSON record containing "side_effects": false. It demonstrates the selected authorization outcome, not an actual file write or proof that an MCP tool is safe.
Discovery fails before authorization starts
Inspect the metadata URL supplied by the challenge:
curl --include 'http://127.0.0.1:8765/.well-known/oauth-protected-resource'
The fixture publishes its resource identifier and a synthetic authorization-server location. It does not provide an authorization endpoint. In your actual deployment, check that the selected authorization server publishes usable metadata and that its declared issuer agrees with the expected issuer. For resource URLs with a path, check the protocol's path-aware well-known discovery rules rather than guessing one root URL. MCP discovery requirements, RFC 8414 metadata validation.
If a proxy serves a login page or rewrites a metadata response to the website's homepage, fix that route. Receiving HTML where the client expects metadata is a routing problem, not evidence that OAuth is unsupported.
Client registration fails
Record which registration path the client attempted. An available pre-registration takes precedence; CIMD depends on advertised support, and DCR remains a deprecated compatibility option. Do not assume every authorization server has a registration_endpoint.
Check redirect URIs and issuer-specific credentials. If the selected authorization server changed, credentials issued by the old server should not be silently reused. A CIMD client ID is instead a self-hosted metadata URL, which has a different onboarding model. MCP client registration.
The callback issuer does not match
Keep the expected issuer with the specific authorization request. Validate a present iss before sending the authorization code to any token endpoint. An issuer mismatch should stop the exchange, rather than be repaired by trimming a slash or changing letter case. RFC 9207.
MCP also requires rejection of a missing iss when metadata advertises authorization_response_iss_parameter_supported: true. With no advertised support and no iss, that check allows proceeding. A missing parameter and a mismatched parameter are different cases. MCP authorization response validation.
The lab self-test covers advertised and unadvertised support, a wrong issuer, and a trailing-slash mismatch. That comparison assumes the expected issuer came from validated metadata; it cannot make untrusted discovery safe.
Keep a useful diagnostic record
Before escalating a failure, record the protocol and client versions, failing stage, resource identifier, issuer, expected permission, redacted challenge, and request correlation reference. Omit tokens, authorization codes, verifiers, secrets, and customer payloads.
Repeat the negative cases against your deployed implementation using disposable identities. Confirm that denied requests never reach the consequential action, and distinguish a policy denial from a transport error. Use the MCP deployment review checklist to connect these results to tool permissions, evidence, and an accountable owner.
Use this with your team
Put the guidance into practice with the editable mcp authorization lab.
Download Node.js: MCP authorization lab Explore the template