Token Exchange
The primitive under on-behalf-of flows, ID-JAG, identity chaining and transaction tokens.
Flows / Delegation chains
Trade the token you were given for a new one that names both the user and the service now acting for them.
An agent calls a tool. The tool needs to call something else to do its job. What credential does it use? Forwarding the token it received is the tempting answer and the wrong one: that token was issued for the tool, not for the downstream API, and passing it along makes every hop a place where it can be stolen and replayed.
Token exchange is the standard alternative. The middle service presents the token it received and asks the authorization server for a new token aimed at the next hop. The new token can keep the user as its subject while adding an act claim that names the service acting for them. Downstream, the API can see the whole story: who this is for, and who is doing it.
9 steps between 4 parties. Each step shows the message and who holds which credential afterward. Use ←→ or select any arrow.
Drag to see every party and step. Tap a step to jump to its explanation.
The agent already holds an access token obtained with the user’s consent. Its audience is the tool server.
{
"iss": "https://auth.example",
"sub": "user:alice",
"client_id": "research-agent",
"aud": "https://tools.example/mcp",
"scope": "reports.generate"
}Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
The token is valid here. But to build the report the tool must read from a data warehouse, and token A is not addressed to the warehouse. The tool must not forward it. The MCP specification forbids this outright, calling it token passthrough.
Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
The tool authenticates as itself and presents token A as the subject_token. It names the audience it needs and the narrowest scope that will do.
POST /token HTTP/1.1
Host: auth.example
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <tool server credentials>
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=<token A>
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&resource=https://warehouse.example/api
&scope=sales.readWho holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
This is the control point. The server checks that token A is valid, that this client is allowed to exchange tokens, that the requested audience is permitted for it, and that the requested scope does not exceed what the user originally granted.
Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
Token B is addressed to the warehouse. Its subject is still Alice. The act claim says the tool server is the party actually presenting it. If the tool calls yet another service and exchanges again, the previous actor is nested inside the new one, so the chain is preserved.
{
"iss": "https://auth.example",
"sub": "user:alice",
"aud": "https://warehouse.example/api",
"scope": "sales.read",
"exp": 1794269100,
"act": {
"sub": "https://tools.example/mcp"
}
}Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
Token A stays where it is. Only token B crosses this boundary.
Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
The warehouse can apply Alice’s row-level permissions and a rule such as “the reporting tool may read sales data but not payroll,” and can log both identities.
Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
The response goes to the tool.
Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
The agent never held a credential for the warehouse. If the agent’s context is compromised, the attacker gets token A, which is good only at the tool.
Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
sub and no act claim, the downstream API believes the user is calling directly. That is impersonation. Sometimes it is what you want; you should know which one you are getting.act is emitted. Test with the tokens you will really get.In this picture the agent appears in token A as client_id and vanishes from token B unless the authorization server carries it forward. Several current drafts are about exactly this gap: how to represent an agent, as distinct from the application hosting it, in the act chain. See the standards tracker.
AWS describes an on-behalf-of exchange for agents in a reference implementation on Amazon Bedrock AgentCore: Propagate user authorization context in AI agents, published in August 2026. AgentCore Identity exchanges the signed-in user’s identity at Salesforce’s token endpoint for a user-scoped token, and Salesforce’s sharing rules decide what comes back. It is a documented path, described from the article and not tested here.
The same article protects two other data sources using mechanisms other than RFC 8693 token exchange, with different enforcement boundaries. DynamoDB access is limited by IAM, through AssumeRoleWithWebIdentity with session tags. A knowledge base is filtered in the agent’s own code, which AWS calls application-layer enforcement.
This is not workload identity. In workload identity federation the agent proves what it is and receives access of its own. Here a user’s authority travels with the request, and the downstream system applies that user’s permissions. An agent often needs both: its own identity to authenticate the exchange, and the user’s token as the subject.
See the full tracker for status and links.
The primitive under on-behalf-of flows, ID-JAG, identity chaining and transaction tokens.
Required by MCP. An agent talks to many servers; this is what stops a token for one being replayed at another.
The usual carrier for act and other agent-related claims.
The most widely implemented authorization profile written specifically for agents and tools.
The company identity provider decides which agents may reach which apps for which employees. No per-app consent screens.
Carry who-is-this-for across an organizational boundary, with each side keeping control of its own tokens.
Inside your own infrastructure, replace the access token with a short-lived token that pins down one transaction and travels the whole call chain.
The baseline. A person signs in, approves specific scopes, and the agent receives a token that says so.