OAuth token exchange (RFC 8693) swaps a broad token for a narrow, audience-bound one. How delegation, impersonation, and the act claim work for AI agents.
Right now, somewhere in your stack, an AI agent is holding a token that was issued to a person. It can reach every mailbox, repository, and customer record that token unlocks. When it acts, the audit log names the human, not the agent.
That is not a permissions problem you can solve with better scopes on the original token. It is a problem of the wrong token being in the wrong hands. OAuth token exchange is the standard built to fix it: a grant type that takes a broad credential and hands back a narrow one, stamped with who is actually carrying it.
OAuth token exchange is an OAuth 2.0 extension, defined in RFC 8693, that lets a client trade one security token for another. The client presents a token it already holds, the authorization server validates it against policy, and it returns a different token with a narrower scope, a different audience, a shorter lifetime, or a different subject. RFC 8693 frames this as a protocol for a Security Token Service that issues tokens representing impersonation and delegation.
The endpoint that performs the swap is acting as a Security Token Service (STS): the component trusted to mint tokens for one trust domain based on tokens presented from another. In OAuth terms it is just the token endpoint, invoked with the grant type urn:ietf:params:oauth:grant-type:token-exchange.
The point of the exchange is the difference between what goes in and what comes out.
| Property | The token going in | The token coming out |
|---|---|---|
| Audience | Broad, often the whole platform | One named resource server |
| Scope | Everything the user consented to | Only what this task needs |
| Lifetime | Session length, sometimes hours | Minutes, sized to the call |
| Subject | The user | The user, unchanged |
| Actor | Absent | The agent, recorded in the act claim |
That last row is the one that matters most, and it is the one most implementations skip. We will come back to it.
OAuth was designed around a client that a user could see. You clicked "allow", the app got a token, and the app did a small number of predictable things with it. The blast radius was bounded by the fact that a human was driving.
Agents removed the human from the loop without removing the human's credentials. Three things changed at once:
The instinct is to give the agent its own service account and move on. That fails differently: now the agent can do everything for everyone, and you have lost the connection to the person who asked for the work. What you actually need is both facts in one credential, which means the agent needs an identity of its own as a non-human principal before an exchange can say anything useful about it.
That is where token exchange comes in. It is the mechanism that carries two identities in one token: the user on whose behalf the call is made, and the agent making it.
In sequence:
subject_token representing the user, and (for delegation) an actor_token representing itself.act claim identifying the agent.Step 2 is the important one architecturally. It is the single point where a policy decision can be attached to a specific action, which is why the exchange endpoint tends to become the enforcement seam in an AI agent architecture rather than a plumbing detail.
RFC 8693 adds one grant type and a handful of parameters to the existing token endpoint. There is no new protocol to deploy.
| Parameter | Required | What it does | Why it matters for agents |
|---|---|---|---|
grant_type | Yes | Fixed value urn:ietf:params:oauth:grant-type:token-exchange | Signals the exchange instead of a fresh authorization |
subject_token | Yes | The token representing the party on whose behalf the request is made | This is the user, and it stays the user |
subject_token_type | Yes | URI naming the token's type (access token, ID token, JWT, SAML assertion) | Lets you exchange an enterprise assertion, not just an access token |
actor_token | No | The token representing the party the rights are being delegated to | Present means delegation. Absent means impersonation. This is the accountability switch |
actor_token_type | With actor_token | URI naming the actor token's type | Required whenever an actor token is sent |
audience | No | The logical name of the intended recipient | Binds the result to one service so it cannot be replayed elsewhere |
resource | No | URI of the target service | The URI form of audience binding, defined by RFC 8707 Resource Indicators |
scope | No | Requested scopes for the new token | Where you drop from "everything" to "read this one calendar" |
requested_token_type | No | The type of token you want back | Ask for an access token for an API call, or an ID token to pass identity onward |
Two rules govern the result. The issued token must never carry more privilege than the subject token already had, and the authorization server is free to return less than you asked for. A conforming server narrows silently, so never assume the scope you requested is the scope you received. Read it back.
The response looks like an ordinary token response with two additions: issued_token_type, which tells you what you actually got, and the requirement that token_type be set to N_A when the issued token is not a bearer token.
| Response field | Meaning |
|---|---|
access_token | The issued token, whatever its type. The name is historical |
issued_token_type | URI naming what was returned. Always check it, because the server may not have granted what you requested |
token_type | Bearer, or N_A if the issued token is not usable as a bearer token |
expires_in | Lifetime of the new token. Should be short |
scope | The scopes actually granted, which may be narrower than requested |
Inside a JWT result, two claims carry the delegation story:
| Claim | Sits on | What it asserts |
|---|---|---|
sub | The issued token | The user. Unchanged by delegation |
act | The issued token | The current actor, the agent. Nests when delegation is chained, so the most recent actor is outermost |
may_act | The subject token | Who is permitted to act for this subject. The authorization server's pre-authorization of the delegation |
A delegated token for an agent called invoice-bot acting for dana@example.com carries sub of dana, an act naming invoice-bot, an aud of one billing API, and a scope of one operation. Every downstream log line now answers two questions instead of one: who wanted this, and what performed it. That pairing is what makes agent observability and audit trails possible at all, and it is why the exchange should mint short lifetimes rather than reuse one long-lived token. If you have not settled your lifetime policy yet, start with how short-lived credentials work and how long a token should actually live.
RFC 8693 supports two outcomes, and the specification is precise about the difference. Impersonation means the agent is given the user's rights and is indistinguishable from the user in that context. Delegation means the agent acts for the user while remaining itself, with both identities present in the token. Both are defined normatively in the specification rather than left to convention.
| Question | Impersonation | Delegation |
|---|---|---|
Is actor_token sent? | No | Yes |
| What does the resource server see? | The user | The user, acted for by the agent |
| Can you attribute an action to the agent? | No | Yes, from the act claim |
| Can you revoke the agent without locking out the person? | No | Yes |
| Can policy treat agent traffic differently? | No, it is invisible | Yes, the actor is a policy input |
| Where it is still reasonable | Break-glass tooling and legacy resource servers that cannot read act | Effectively every agent use case |
The rule: if an autonomous system is making the call, send the actor token. Impersonation is a deliberate decision to destroy evidence, and it should require the same justification as turning off logging. When a resource server genuinely cannot understand act, keep the delegation at the exchange and record the actor there, rather than pretending the agent was a person.
Delegation also gives you somewhere to put a human. Because the exchange is a discrete, policy-evaluated moment, it is the natural place to require step-up authentication before a high-risk exchange instead of at the point the agent already holds a credential.
Three shapes of agent delegation cover most real deployments.
A user asks an agent to do something in a system they have access to. The agent exchanges the user's session token for a task-scoped token: one audience, one or two scopes, minutes of life. The agent never sees the original credential's full reach, and if the agent is later found to have been manipulated, the damage is bounded by the scope of the exchange rather than by the user's job title. Identity platforms increasingly ship this as a managed capability: Frontegg's identity product for AI agent builders separates acting on behalf of a user from acting as the application itself, which is the same delegation-versus-service-account decision expressed as configuration.
An orchestrating agent hands work to a specialist agent. Each hop performs its own exchange, and the act claim nests: the token names the user as subject, the specialist as the current actor, and the orchestrator inside it. The result is a chain of custody you can read backwards from any log line. This is what makes delegation safe in multi-agent systems, where the alternative is a shared token that nobody can attribute. Cap the depth of the chain: every hop is another chance to widen scope by accident.
The agent needs a resource governed by a different authorization server, in a different trust domain. Token exchange is the mechanism that carries an assertion from one domain and produces a usable token in the next, which is the pattern the IETF's work on identity and authorization chaining across domains formalizes for enterprise deployments. In MCP deployments this is the everyday case, because the client, the server, and the downstream API frequently answer to three different identity providers. See how MCP identity and authentication fit together for the surrounding wiring.
The tempting shortcut is passthrough: the server receives the caller's token and forwards it, unmodified, to whatever it calls next. It works on the first try, which is why it survives into production.
It also creates a confused deputy: a privileged intermediary using its position to perform an action the original caller was never authorized to request, because the downstream service cannot tell the difference between a token the intermediary validated and one it merely relayed. The Model Context Protocol specification forbids the pattern outright, requiring servers to reject tokens that were not issued for them and stating that an MCP server must not pass through the token it received from its client.
Token exchange is what you do instead. The server validates the inbound token, then exchanges it for a separate token whose audience is the downstream API, preserving the user in sub and itself in act. Three properties follow:
Where the exchange runs is an architecture choice. Doing it inside each service spreads the policy across every codebase. Doing it at a gateway keeps one place to change the rules, which is the usual argument for handling access control at the MCP gateway. If you are still mapping the basics, MCP authentication covers how the inbound side works.
Token exchange answers exactly one question: how the credential gets narrower. It is one control among several, and it is weak on its own.
| Question | Control | Where it is covered |
|---|---|---|
| May this agent do this at all? | Authorization policy | Agent authorization sets the rules the exchange enforces |
| How does the token get narrower? | Token exchange (RFC 8693) | This page |
| How long does the credential live? | Short-lived credentials | Ephemeral credentials and token lifetime |
| Who approved this specific action? | Human approval gate | Human in the loop AI covers when an agent must stop and ask |
| Is the person really there right now? | Step-up authentication | Step-up authentication and when to trigger it |
| What actually happened afterwards? | Audit and observability | AI observability and agent audit logs |
Read across that table and the shape of the thing appears: policy decides, the exchange enforces, the lifetime limits, the human approves, and the log proves. A stack missing any one row has a gap somebody will eventually find.
Most token exchange integrations fail in the same handful of ways.
| Symptom | Likely cause | Fix |
|---|---|---|
invalid_target | The requested audience or resource is unknown to the authorization server, or the client is not allowed to target it | Register the resource and confirm the exact URI, including trailing slash and scheme |
invalid_request on a delegation attempt | actor_token sent without actor_token_type, or an unsupported token type URI | Always send the type alongside the token; the two are a required pair |
| Delegation silently becomes impersonation | The actor token was dropped by a proxy or never sent, and the server defaulted | Assert on the presence of act in the issued token, and fail closed when it is missing |
| Exchange rejected for an authorized agent | The subject token has no may_act naming this actor | Pre-authorize the delegation relationship at the identity provider rather than at call time |
| Downstream 401 with a valid-looking token | Audience mismatch: the resource server is correctly rejecting a token minted for a different service | Exchange per target rather than reusing one token across APIs |
| Scope narrower than requested, calls failing later | The server downscoped and the client never read the response scope | Read back scope and issued_token_type on every exchange |
| Exchange latency on every tool call | No caching of short-lived tokens per subject, actor, and audience triple | Cache by that triple for the token's lifetime, and never across subjects |
The specification is narrow on purpose, and it is worth being clear about the edges rather than discovering them in an incident review.
act claim meaningless.may_act rather than allowing any client to act for any subject.actor_token and actor_token_type. Treat a missing act claim in the result as a failure.aud on every resource server, and reject anything not issued for you.Agent delegation is an active area at the IETF, and the work builds on token exchange rather than replacing it.
None of this is settled, and betting an architecture on a draft is a choice to keep rewriting it. Build on RFC 8693 today, and keep the exchange behind an interface you control so you can adopt whatever wins.
It is used to trade one token for another with different properties: a narrower scope, a single audience, a shorter lifetime, or a different token type. Services use it to call downstream APIs on a user's behalf without forwarding the user's original credential, and AI agents use it to obtain task-scoped access.
Impersonation issues a token in which the client is indistinguishable from the user, so downstream systems see only the person. Delegation keeps both identities: the user stays in the subject claim and the client appears in the actor claim. Delegation preserves attribution and lets you revoke the agent alone.
The actor_token identifies the party receiving the delegated rights, normally the agent or service making the call. Sending it, with its matching actor_token_type, is what turns an exchange into delegation and produces the act claim. Omit it and the authorization server issues an impersonation token instead.
They solve the same problem, and vendor on-behalf-of flows are usually implementations or close relatives of RFC 8693. The difference is portability: token exchange is the standardized grant type, while an on-behalf-of flow may add vendor-specific parameters and behavior. Prefer the standard shape where your provider supports it.
No. OAuth 2.1 consolidates the core framework and removes legacy grants such as the implicit and password flows. Token exchange remains a separate extension defined by RFC 8693, and you enable it alongside OAuth 2.1 rather than getting it automatically.
It gives the server a correct alternative. Instead of forwarding the inbound token, the server validates it, then exchanges it for a new token whose audience is the downstream API, with the user as subject and itself as actor. The MCP specification requires this by forbidding passthrough outright.
Token exchange is a small specification with an outsized consequence. The moment a broad credential becomes a narrow one is the moment you decide whether anybody will be able to reconstruct what an agent did and why. Get it right and every action carries the human who asked and the agent that acted. Get it wrong, or skip it, and your logs will confidently attribute an autonomous system's mistakes to an employee.
Doing that consistently across a fleet of agents is an operational problem, not a protocol one. It means every agent having a real identity, every exchange evaluated against policy, and every actor chain landing somewhere you can query later. That is what an identity-native foundation for AI agents is for. If you want to see what per-action delegation and attribution look like on your own stack, book a walkthrough with our team.
Keep reading
Human in the loop AI puts a person on the calls an agent should not make alone. Which actions need approval, how to design the checkpoint, what auditors want.
Written by
Agen.co
What agent authorization is, which model to use, how delegated authority travels in a token, and where the decision belongs so a prompt cannot move it.