When an agent calls APIs for a user, use delegation, not a shared service account
Giving the agent an admin account gets the demo working this afternoon. When something goes wrong, though, that shortcut can't answer the first question the security team will ask.
In brief
- When every user shares one service account or API key, the trail is lost: nobody can tell which user caused the agent to act.
- Use delegation. The new token carries the user's identity, the act claim records the agent, and permissions never exceed the user's own.
- Don't pass the client's token straight through to downstream APIs. Check the audience, exchange it for a new token, request narrow scopes and return MFA requirements to the client.
It is your second week on site, and the internal support agent you are building can already read tickets and update orders. To make Friday’s demo, one of the customer’s engineers suggests giving the agent a service account with admin rights on the ticketing system.
The suggestion sounds entirely reasonable. It is also the point at which many FDEs take on a security debt that is very hard to pay back later.
The problem is the logs. Three months on, if a ticket is closed by mistake or customer data is read without authorisation, the security team will ask who did it. With a shared credential, you cannot answer.
Auth0 describes exactly this situation when discussing static API keys shared by agents: there is no way to know which user, or which of the agent’s actions, used the key.
According to Auth0, that lack of an audit trail is unacceptable for security, compliance and incident response. If you want your agent to get through a security review at a large enterprise, you need to have the skills in this article down cold.
Should the agent become the user, or act alongside them?
RFC 8693 defines OAuth 2.0 Token Exchange, a protocol for requesting security tokens from an authorization server. It supports both impersonation and delegation. The two sound alike but leave very different logs.
On impersonation, the RFC says that when A impersonates B, A is B within the rights of the token. The downstream API sees only B, and any trace of the party actually acting disappears. With delegation, A keeps its own identity, separate from B. An agent acting for a user should choose the second.
Impersonation
- The token carries only the user's identity
- The downstream API cannot tell the agent from the user
- The log says the user did it, even though the agent did
Delegation
- The token carries the identity of both the user and the agent
- The act claim records the party acting
- The log shows who requested and who performed the action
The tool for recording delegation is the act (actor) claim in a JWT. RFC 8693 created this claim to state explicitly that a token was issued through delegation, and who the acting party is.
A complete flow, step by step
Picture a support agent named Lan asking the agent to summarise the open tickets. The chat application sends the agent Lan’s token, whose audience is the agent itself. The agent does not take that token and call the ticketing system with it. Instead it sends a token exchange request to the authorization server, with a grant_type value defined by RFC 8693:
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=<token Lan sent to the agent>
&actor_token=<the agent's own identity token>
&scope=tickets.read
If the request is accepted, the new token’s payload will look roughly like this. Lan remains the subject, the agent sits in act, and the scope grants read access only:
{
"sub": "[email protected]",
"scope": "tickets.read",
"act": { "sub": "support-agent" }
}
As a result, every line in the ticketing system’s log answers two questions: who asked, and who acted. That is precisely what a shared service account cannot do.
On-behalf-of: three constraints every FDE should know by heart
If the customer runs Microsoft Entra, the concrete version of this idea is the On-Behalf-Of (OBO) flow. Microsoft describes OBO as OAuth delegation, used to carry the user’s identity and permissions through a chain of requests. Its documentation sets out three constraints FDEs should remember.
First, OBO uses only delegated scopes, not application roles. The middle tier therefore cannot give a user more permissions than they already have. If Lan cannot delete tickets, an agent acting for Lan cannot delete them either, even if a prompt injection tries to trick it into doing so.
Second, an application may not exchange a token that was issued to a different application. The incoming token’s audience must be the agent itself. A token issued for another API must be rejected, not forwarded.
The third is the one most often missed. When a downstream API requires Conditional Access, such as MFA, the middle tier cannot satisfy it on its own. It must return the error to the client so the client can take the user through the authentication step.
This is also the clearest reason a service identity cannot stand in for a user: a service has no phone to approve an MFA prompt.
Three common mistakes on customer sites
The first is token passthrough: accepting a token from the client and passing it unchanged to a downstream API. The Model Context Protocol security guidance calls this an anti-pattern, and the authorization specification forbids it outright.
The reason is that the downstream API’s logs will record the request as if it came from a different source with a different identity, not from the server that actually forwarded it.
The second is requesting every scope up front “so we don’t have to ask again”. The MCP documentation warns that poorly designed scopes increase the damage when a token leaks, frustrate users and blur the audit trail.
For a summarisation task, request only tickets.read, and ask for write access only when the user actually asks for an update.
The third is letting the agent hold each provider’s refresh tokens itself. Auth0’s Token Vault pattern addresses this: the agent holds only Auth0 tokens and exchanges them for provider tokens when needed, never touching the provider’s refresh tokens.
If the customer’s identity provider already supports something similar, use it rather than building your own token store.
Do it yourself on the next project
Start by drawing the call chain: user, client, agent, then each downstream API. On every arrow, write down which token is travelling and what its audience is. The drawing usually shows at once where someone intends to forward a token or share a key.
Next, in the agent, check the audience of every incoming token before doing anything else. Exchange tokens with token exchange or OBO, request the narrowest scope that covers the task, and return Conditional Access errors to the client intact rather than swallowing them and retrying with a different credential.
Finally, sit down with the customer’s security team and read a real log line from the downstream API to see whether it shows both the user and the agent.
For your career, this is a skill that is easy to demonstrate. When reading FDE job descriptions, look for mentions of OAuth, identity or integration with enterprise systems. If they are there, put this experience at the top.
On your CV, don’t just write “experience with OAuth”. Describe how you designed a delegation flow that made every API call by the agent traceable to the right user.
A sentence like that tells an interviewer you have built systems that can pass a real security review.
This week’s exercise: take an agent you have written, decode the token it uses to call downstream APIs, and ask yourself whether, if an incident happened tomorrow, that token would tell you who asked the agent to act. If the answer is no, you know what to fix before your next demo.
Was this article useful?
Thanks for the feedback!
6 sources
- RFC 8693 - OAuth 2.0 Token Exchange · 2020-01
- RFC 8693 - OAuth 2.0 Token Exchange · 2020-01
- Microsoft identity platform and OAuth2.0 On-Behalf-Of flow - Microsoft identity platform | Microsoft Learn · 2025-01-04
- Security Best Practices - Model Context Protocol
- API Keys and AI Agents: Four Common Risks · 2025-09-02
- Auth0 Token Vault: Secure Token Exchange for AI Agents · 2025-10-09