Delegation chain explorer
An MCP client obtains a token for an MCP server
The baseline chain of MCP Authorization 2026-07-28: an agent host discovers where a tasks server's authorization server is, identifies itself with a client ID metadata document, runs the OAuth 2.1 code flow with PKCE and a resource indicator, and presents the token the server was issued for. The server validates it and uses a token of its own for the API behind it.
AttackMissing audience check
The MCP server validates the signature and expiry but not the audience. An attacker who obtained a token issued for a different resource behind the same authorization server presents it here, and the server accepts a token that was never meant for it.
- Defeats Audience validationMCP serverListed servers under MCP Authorization 2026-07-28: 0 supported, 0 partial, 0 unsupported, 34 unknown, 5 not applicable.
The chain, step by step
Step 1: Agent host to Tasks MCP server
The host has no token for this server yet, so it starts with the request any client makes first. Everything it learns about where to get a token comes from the answer.
Authorization Server Discovery › Protected Resource Metadata Discovery RequirementsMCP Authorization 2026-07-28
Step 2: Tasks MCP server to Agent host
The server must point at its protected resource metadata, either in this challenge or at the well-known location; this server does both.
Authorization Server Discovery › Protected Resource Metadata Discovery RequirementsMCP Authorization 2026-07-28
Step 3: Agent host to Tasks MCP server
3. Protected Resource MetadataOAuth 2.0 Protected Resource Metadata rfc
Step 4: Tasks MCP server to Agent host
The resource identifier is what the client will ask the token to be bound to; the authorization server list is where it will ask.
Authorization Server Discovery › Authorization Server LocationMCP Authorization 2026-07-28
Step 5: Agent host to auth.tasks.example
3. Obtaining Authorization Server MetadataOAuth 2.0 Authorization Server Metadata rfc
Step 6: auth.tasks.example to Agent host
The issuer must match the URL the client asked; the client keeps the metadata keyed by that issuer.
Authorization Server Discovery › Authorization Server Metadata DiscoveryMCP Authorization 2026-07-28
Step 8: auth.tasks.example to Alex
The authorization server fetches the document at the client_id URL, checks that the redirect URI is one it lists, and shows Alex who is asking.
Client Registration › Client ID Metadata DocumentsMCP Authorization 2026-07-28
Step 10: Agent host to auth.tasks.example
Security Considerations › Authorization Code ProtectionMCP Authorization 2026-07-28
Step 11: auth.tasks.example to Agent host
The authorization server verified the code verifier against the challenge and issued a token whose audience is the resource the client asked for.
Security Considerations › Token Audience Binding and ValidationMCP Authorization 2026-07-28
Access token for the Tasks MCP servertyp at+jwt · alg ES256 · kid auth-2026-1
- iss
- https://auth.tasks.example
- sub
- alex
- aud
- https://mcp.tasks.example/mcp
- client_id
- https://agent.example/client.json
- scope
- tasks:read tasks:write
- exp
- 1790000000
- iat
- 1789996400
- jti
- 7f2c
Unchanged since the previous token in this chain. Shown in the RFC 9068 JWT profile; an opaque token would carry the same binding on the server side.
Step 12: Agent host to Tasks MCP serverreplaces "bearer-call"
The token is genuine and unexpired, signed by the same authorization server, but its audience is another resource.
Security Considerations › Token Audience Binding and ValidationMCP Authorization 2026-07-28
A token for another resource, replayedtyp at+jwt · alg ES256 · kid auth-2026-1
- iss
- https://auth.tasks.example
- sub
- alex
- audchanged
- https://notes.example/mcp
- client_idchanged
- https://other-agent.example/client.json
- scopechanged
- notes:read
- exp
- 1790000000
- iat
- 1789996400
- jtichanged
- c4d1
4 claims differ from the previous token in this chain.
Step 13: Tasks MCP server to itselfreplaces "validate"
Without the audience check every token the authorization server ever issued for any of its resources opens this server.
Security Considerations › Token Audience Binding and ValidationMCP Authorization 2026-07-28
Step 14: Tasks MCP server to Tasks API
The server never forwards the token it received. It holds credentials of its own for the API and obtains a token whose audience is the API, so the API can tell who is calling on whose behalf.
Security Considerations › Access Token Privilege RestrictionMCP Authorization 2026-07-28
The server's own token for the Tasks APItyp at+jwt · alg ES256 · kid auth-2026-1
- iss
- https://auth.tasks.example
- sub
- alex
- audchanged
- https://api.tasks.example
- client_idchanged
- tasks-mcp-server
- scopechanged
- tasks:read
- actadded
{ "sub": "tasks-mcp-server" }- expchanged
- 1789999000
- iatchanged
- 1789996500
- jtichanged
- 9b10
7 claims differ from the previous token in this chain.
Step 15: Tasks MCP server to Agent host
Authorization › Access Token UsageMCP Authorization 2026-07-28
Requirements this chain exercises
- resource_metadata in the 401 challengeMCP server
- PRM reachable at a well-known URIMCP server
- PRM lists an authorization serverMCP server
- Authorization server metadata discoverableAuthorization server
- Client ID Metadata Documents supportedAuthorization server
- PKCE on every authorization requestClient
- PKCE with S256 advertisedAuthorization server
- resource parameter on token requestsClient
- Resource indicators honouredAuthorization server
- Issuer identifier in authorization responsesAuthorization server
- Exact iss comparisonClient
- Bearer token only in the Authorization headerMCP server
- Audience validationMCP server
- No token passthrough to upstream APIsMCP server