One more hop
So far the agent has called the calendar API directly. Often something sits in between. Alice asks the agent to find a time for a meeting. The agent calls a scheduling tool, which in MCP would be a server. The tool needs to see Alice’s calendar, so it calls the calendar API.
The agent has a token for the tool: Alice approved it, and its audience is the tool. Now the tool has to call the calendar API. What does it send?
There are three things it could reach for. Before you look, guess which of them lets the calendar API answer all three of its questions.
The tool sends the calendar API: The token it was handed
Do not build this. The token was issued for the tool, not for the calendar API. Sending it on is called token passthrough, and MCP forbids it.
What arrives at the calendar API
{
"sub": "alice",
"client_id": "calendar-assistant",
"aud": "https://scheduler.example",
"scope": "meetings.schedule"
}| Is this for Alice? | Yes | The token names her. |
|---|---|---|
| Which software is calling? | No | The token names the agent’s app. The tool in the middle is invisible. |
| Was this issued for me? | No | aud is the scheduling tool. The calendar API has to ignore the address to accept it. |
This is the tempting one: the tool already holds a token, so why not use it? Because it only works if the calendar API stops checking who a token is for, and then any service that is ever handed a token from that issuer can use it there.
The tool sends the calendar API: Its own API key
What arrives at the calendar API
GET /events?day=tomorrow HTTP/1.1
Host: calendar.example
X-API-Key: sk_scheduler_41c0…
X-User: alice| Is this for Alice? | No | alice is only the tool’s word. The key is the same for every user. |
|---|---|---|
| Which software is calling? | Partly | The tool, by its key. Not the agent behind it. |
| Was this issued for me? | Yes | The calendar API issued the key itself. |
The first lesson again, one hop further along. The calendar API sees the tool and nobody else, so the tool needs access to everyone’s calendar, and the only thing keeping Alice’s request inside Alice’s calendar is the tool’s own code.
The tool sends the calendar API: A new token, made for this hop
What arrives at the calendar API
{
"sub": "alice",
"aud": "https://calendar.example",
"scope": "calendar.read",
"act": { "sub": "scheduling-tool" }
}| Is this for Alice? | Yes | sub is still Alice. |
|---|---|---|
| Which software is calling? | Yes | A second name has been added: act, the tool acting for her. |
| Was this issued for me? | Yes | aud is the calendar API. |
The tool takes the token it was handed back to the authorization server and asks for a new one, for the next hop. The server decides whether this tool may act for Alice at the calendar API, and if so says exactly that in a fresh token. Each hop ends up holding a token that works in one place.
| The tool sends the calendar API | Is this for Alice? | Which software is calling? | Was this issued for me? |
|---|---|---|---|
| The token it was handedDo not build this | Yes | No | No |
| Its own API key | No | Partly | Yes |
| A new token, made for this hop | Yes | Yes | Yes |
Why forwarding is the dangerous one
Forwarding feels harmless. It is the same user and the same request, and the token is right there. The harm is in what it requires of the calendar API: accepting a token that was addressed to someone else.
An API that does that can be used by any service holding any token from the same authorization server. A tool you connected for one purpose can quietly use your token for another. And an API that accepts tokens that were not addressed to it can be steered, by any caller holding one, into acting with authority that caller should not have. Security people call a service misused that way a confused deputy.
The audience check from the token lesson is the defense, and it only works if no service ever asks another to skip it.
What to do instead
The tool asks for a token of its own for the next hop. It takes the token it was handed back to the authorization server and asks for a new one, addressed to the calendar API. The authorization server decides whether this tool may act for Alice there, and if so issues it. That trade is a token exchange, and this is what then arrives at the calendar API:
{
"sub": "alice",
"aud": "https://calendar.example",
"scope": "calendar.read",
"act": { "sub": "scheduling-tool" }
}Still about Alice, now addressed to the calendar API, and no wider than this step needs. So the rule is short: exchange, never forward.
Two ways to write “for Alice”
A token made for the next hop can be written two ways.
- It can name only Alice. The calendar API then believes Alice is calling in person, and its logs will say so. This is impersonation.
- It can name Alice, and separately the software acting for her. This is delegation, and the second name is called the actor. It is the
actline in the token above.
Delegation is the one to want. The API can apply Alice’s permissions and the tool’s limits together, block one misbehaving tool without locking Alice out, and say afterward what did what. With impersonation the log shows Alice doing things at 3 a.m. that Alice never did.
One caution. Whether the new token carries an actor depends on the authorization server that issues it, and whether anything is done with it depends on the API. Check what your authorization server actually issues, and what your API actually reads, before you rely on it.
Where you will meet this
- An MCP server that calls another API. It must not pass along the token the client sent it. It gets a token of its own for the API behind it, by exchange or by asking the user to connect that account directly.
- An agent that hands work to another agent. The same question one level up: what does the second agent receive, and what can the service behind it tell?
- A request that crosses into another company. Their authorization server does not know your users, so there are two trades: one at home for a short-lived grant, and one there for a token.
- A request passed between services inside your own infrastructure. One variant makes a single exchange at the edge, for a short-lived token built to travel from service to service. What is never forwarded is a token addressed to someone else.
Check yourself
Answer before you read on. Nothing is recorded.
What to keep
- A forwarded token only works if the next API stops checking the audience, and then any token from that issuer works there.
- Delegation names the person and the software acting for them. Impersonation names only the person. Prefer delegation.
- Access should shrink as it travels down a chain. It should never grow.
One rule
A service never passes on a token that was issued for itself. Exchange, never forward.
The names for these
The rest of this guide, and every specification, uses these terms. Each links to its entry in the glossary.
| In this lesson | Its name | Defined as |
|---|---|---|
| Forwarding the token you were handed | Token passthrough | Forwarding a received token to another service instead of obtaining a new one for it. Prohibited by the MCP specification. |
| A service talked into misusing access it was lent | Confused deputy | A service with legitimate authority that is tricked into using it for a caller who should not have it. Agents that forward tokens or share one identity across users are prone to it. |
| Trading a token for a new one, for the next hop | Token exchange | Presenting one token to an authorization server to obtain another, typically for a different audience or with an actor added. |
| A token that names the person and the software | Delegation | Acting for someone else in a way that keeps both identities visible: the token names the subject and, separately, the actor. |
| A token that names only the person | Impersonation | Acting for someone else in a way that makes the software indistinguishable from the person: the token names only the subject. |
| The software named as acting | Actor | The party acting for a token’s subject, as the issuer names it in the act claim. Its presence is what distinguishes delegation from impersonation. It says who was authorized to act, not who is holding the token. |
| What some vendors call the exchange | On-behalf-of | A general term, and some vendors’ product term, for a service obtaining a token to act for the user whose request it is handling. |
Go deeper
The same ground at full depth, when you want it. None of it is needed for the next lesson.
- Token exchangeThe exchange step by step, with the request and the token that comes back.
- Delegation or impersonationFive ways of carrying authority down a chain, compared on five questions.
- Delegation chainsAcross companies, inside one infrastructure, and under a company identity provider.