Delegation Chains and the Confused Deputy in Agent Identity: Safe Impersonation, Token Exchange, and Audit Trails
How AI agents pass authority safely down a delegation chain, why the confused deputy bites, and how token exchange (RFC 8693) keeps audit trails intact.
When an AI agent calls a tool, which then calls a service, which then reads your database, a question hangs over every hop: whose authority is this, really? Get the answer wrong and you have rebuilt a 1970s mainframe bug at machine speed. This article walks the delegation chain end to end — what the confused deputy is, why agents are unusually prone to it, and how token exchange turns a fuzzy “acting on behalf of” into an auditable, revocable record.
What is the safest way to pass identity down an agent delegation chain?
The safest approach is delegation, not impersonation: each hop carries both the original user’s identity (the sub claim) and the identity of the agent or service currently acting (the act claim), so the audit trail never loses track of who initiated the action and who carried it out. The mechanism for minting these scoped, traceable tokens is OAuth 2.0 Token Exchange (RFC 8693). Impersonation — where the agent’s token looks exactly as if the user issued it — is simpler but strips out the actor information, leaving you unable to prove which component did what. As a default, reach for delegation; reserve impersonation for narrow cases where the downstream service genuinely cannot understand an actor claim, and compensate with logging elsewhere.
That single distinction governs nearly every design decision below. Hold onto it: delegation preserves the chain, impersonation flattens it.
What is the confused deputy problem, and why does it matter for agents?
The confused deputy problem is a vulnerability where a privileged intermediary — the “deputy” — is tricked by a less-privileged caller into misusing authority the caller never had. The deputy is not malicious. It is confused. It mixes up two things that look the same but are not: the designation of a resource (which file, which record, which endpoint) and the authorization to touch it.
The term comes from Norm Hardy, who in 1988 formally described the failure class he had seen on the 1970s Tymshare system. A Fortran compiler ran in a privileged directory and held a license to write its own statistics and billing files. A user could ask the compiler to write debug output to a filename of their choosing. Nothing stopped them from naming the system billing file. The compiler dutifully opened it — using its authority, not the user’s — and overwrote the billing records. The user never had permission to that file. The deputy lent its privilege without realizing it.
Why does a forty-year-old mainframe story matter now? Because an AI agent is the most enthusiastic deputy ever built. It holds broad credentials (an OAuth token, a service account, a database connection), it accepts instructions in natural language, and those instructions can arrive from untrusted places: a web page it browses, a document it summarizes, an email it triages. Prompt injection is, at bottom, a confused-deputy attack. The attacker cannot reach your CRM, but the agent can — so the attacker simply persuades the agent to do it. The agent’s ambient authority becomes the attacker’s authority.
Why does ambient authority make agents dangerous?
Ambient authority is permission that hangs in the air around a process rather than traveling with each request. A classic example: a service account key sitting in an environment variable. Any code in that process can use it for anything it permits, and nothing in the request says on whose behalf the call is being made.
For a deterministic microservice, ambient authority is merely sloppy. For an agent, it is combustible. The agent’s behavior is steered by tokens it ingests at runtime, and some of those tokens are adversarial. If the agent’s authority is ambient — “this process can write to the database, full stop” — then any instruction that reaches the agent inherits that power. There is no boundary between “the user asked for this” and “a poisoned web page asked for this,” because the authority was never tied to the user’s request in the first place.
The fix Hardy pointed to was capabilities: bundle designation and authorization into one unforgeable token, so you cannot name a resource without also presenting the right to use it. Modern agent identity does not always use literal capabilities, but it applies the same principle — authority should ride with the request, scoped to exactly what this hop needs, and it should name who is acting.
How does OAuth 2.0 Token Exchange (RFC 8693) implement safe delegation?
RFC 8693 defines a Security Token Service (STS): an endpoint where a caller presents a token it holds and receives a new token, scoped and shaped for the next hop. Instead of forwarding the user’s powerful access token verbatim down five services, each service exchanges it for a narrower one. The original token never leaves the front door.
Two claims carry the whole story:
sub— the subject. The original principal. The human (or root agent) on whose behalf everything ultimately happens.act— the actor. The party currently doing the acting. Its value is a JSON object holding the actor’s own identifying claims.
In a delegation token, both are present: sub says Alice initiated this, and act says the invoicing agent is doing it right now. A downstream service reading that token knows both facts and can enforce policy on either.
A chain of delegation is expressed by nesting act claims. The outermost act is the current actor; each nested act is a prior actor, recording the full path the request traveled. So a token can truthfully say: “Alice’s request, currently carried by the database connector, which received it from the orchestration agent, which received it from the chat front end.” That nesting is the audit trail, baked into the credential itself rather than reconstructed afterward from scattered logs.
A third claim closes the loop on authorization. may_act states, inside the user’s own token, which party is permitted to become an actor on their behalf. When an agent shows up at the STS asking to act for Alice, the STS checks whether Alice’s token authorizes that actor via may_act before issuing anything. Delegation becomes opt-in and verifiable instead of assumed.
Delegation vs. impersonation: which should an agent use?
| Dimension | Delegation | Impersonation |
|---|---|---|
| Claims in token | sub (user) and act (agent) |
sub only — looks user-issued |
| Audit trail | Full: who initiated and who acted | Lossy: the actor disappears |
| Distinguishable from a normal token | Yes, via act |
No — there is no marker that impersonation occurred |
| Policy enforcement | Can gate on the actor | Cannot see the actor |
| Complexity downstream | Service must understand act |
Works with any token consumer |
| Best for agent chains | Default choice | Only legacy consumers that ignore act |
The practical takeaway: an impersonated token is, by design, indistinguishable from one the user issued directly — there is no claim or value that flags it as the product of an impersonation flow. That is convenient and dangerous in equal measure. If something goes wrong, your logs say “Alice did it,” and Alice did not. Delegation refuses that ambiguity. For multi-hop agent systems, where the entire risk surface is the question of who did what, delegation should be the standing default.
How do you keep the audit trail intact across the whole chain?
An audit trail is only useful if it survives every hop. A delegation chain breaks the trail in three common ways, and each has a discipline that prevents it.
1. Don’t collapse to impersonation mid-chain. The moment any service swaps a delegation token for an impersonation token, every actor downstream of that point vanishes from the record. If one hop must impersonate (a legacy API that rejects act), record the actor in that service’s own logs and treat the boundary as a known blind spot, not a default.
2. Bind tokens to a correlation identifier. Issue a single request or trace ID at the entry point and carry it on every exchanged token and every log line. Then “who did what” can be reassembled across services even when they live in different systems. Distributed-tracing context and the nested act chain are complementary: tracing tells you the timeline, act tells you the authority.
3. Log the exchange, not just the use. The interesting security event is often the minting of a token — “the research agent requested an actor token for Alice scoped to read-only inventory.” Logging exchanges at the STS gives you a chokepoint where every grant of delegated authority is visible, independent of whether the downstream call succeeds.
Done well, the audit trail answers the forensic question without guesswork: for any action, you can name the human principal, every agent and service in the chain, the scope each hop held, and the moment each token was issued.
How do you actually prevent the confused deputy in an agent system?
The defenses follow directly from “authority rides with the request, scoped and attributed.”
- Scope every hop to least privilege. Exchange the broad token for the narrowest one the next step needs. The research agent gets read-only inventory, never write access to billing. Even if it is confused, the blast radius is the scope it holds.
- Make authorization explicit with
may_act. Do not let any agent silently act for any user. Require the user’s token to name permitted actors, and enforce that check at the STS. - Separate designation from ambient privilege. Treat instructions that arrive from untrusted content (web pages, documents, emails) as data, not as commands that inherit the agent’s authority. The agent reading a poisoned page should not thereby gain the page’s chosen target.
- Re-check authorization at the resource, not just the gateway. The confused deputy succeeds when the resource trusts the deputy’s privilege instead of the caller’s. The service holding the data should evaluate the
sub/actpair against its own policy on every request. - Prefer short-lived, narrowly-audienced tokens. A token good for one audience and a few minutes cannot be replayed across the system. Token exchange makes this cheap: mint fresh, scoped tokens per hop instead of forwarding one powerful credential everywhere.
None of this is exotic. It is the capability principle Hardy described in 1988, applied to a stack where the deputy now speaks English and follows instructions from strangers.
Where to go deeper
The primary source is worth reading in full: RFC 8693, OAuth 2.0 Token Exchange specifies the sub, act, and may_act claims and the exact request/response shapes. Hardy’s original write-up, The Confused Deputy, is short and remains the clearest explanation of why designation and authorization must travel together. For the agent-specific framing, the Cloud Security Alliance has published research on confused-deputy attacks on autonomous AI agents, connecting the classic bug to prompt injection.
The throughline across all three: identity in an agent system is not a login event at the edge. It is a property that must be carried, scoped, and attributed at every hop — or it is not really there at all.
Frequently asked
What is the difference between delegation and impersonation in OAuth token exchange?
In delegation, the issued token carries both the original user (the sub claim) and the acting agent or service (the act claim), so the audit trail records who initiated the action and who performed it. In impersonation, the token is shaped to look as if the user issued it directly, with no actor claim. RFC 8693 supports both, but delegation preserves accountability while impersonation flattens it.
What is the confused deputy problem in simple terms?
It is when a trusted, privileged program is tricked by a less-privileged caller into using its own authority to do something the caller could not do alone. The program is not malicious — it confuses naming a resource with being allowed to access it. Norm Hardy described it in 1988 using a compiler that overwrote system billing files at a user's request.
Why are AI agents especially vulnerable to confused deputy attacks?
Agents hold broad credentials and take instructions in natural language, including from untrusted sources like web pages, documents, and emails. When an attacker plants instructions the agent ingests (prompt injection), the agent's ambient authority becomes the attacker's authority. The attacker cannot reach the resource, but the agent can, so it acts on their behalf without realizing it.
What do the sub, act, and may_act claims do in RFC 8693?
The sub claim names the original principal on whose behalf the action happens. The act claim names the party currently acting and can be nested to record a full chain of prior actors. The may_act claim, placed in the user's token, states which parties are authorized to act on their behalf, letting the token service verify a delegation request before issuing anything.
How does a delegation chain create an audit trail?
Each act claim can nest the previous one, so the token itself records the full path: the current actor on the outside, prior actors nested within, and the original subject throughout. That nesting is the audit trail, embedded in the credential rather than reconstructed later from separate logs. Pairing it with a correlation ID and logging token exchanges at the STS keeps the trail intact across services.
Can you tell whether a token was created through impersonation?
Generally no. By design, an impersonated token is indistinguishable from one the user issued directly — it carries no specific claim or value marking it as the result of an impersonation flow. That is why delegation, which keeps the act claim, is preferred whenever accountability matters.
How do you stop the confused deputy without breaking agent functionality?
Scope every hop to least privilege via token exchange, require explicit authorization with may_act, treat untrusted content as data rather than commands, re-check authorization at the resource itself instead of trusting the deputy, and use short-lived, narrowly-audienced tokens. These apply the capability principle — authority travels with the request, scoped and attributed — without disabling the agent.