OAuth's On-Behalf-Of flow for AI agents
How a new IETF draft extends OAuth so AI agents can act for users with explicit consent and a clean audit trail.
When an AI agent calls an API for you, the API has no clean way to tell that an agent did the work. The token says you authorized it. The audit log shows your username. A script could have run. An agent could have reasoned its way there. Someone could have stolen your session. The trail looks the same.
A new IETF Internet-Draft proposes a fix. It extends OAuth's authorization code flow with two parameters that carry the agent's identity through the consent screen and into the access token. The result is that a user can grant a specific agent specific powers, and every downstream system can see exactly who acted.
This article walks through what the draft does and how it compares to existing approaches. We will cover Microsoft's On-Behalf-Of, RFC 8693 token exchange, and the new draft itself. Plus what builders should know to design around all three.
Why existing approaches fall short
OAuth has several ways to handle delegation. None fully fit an AI agent acting for a user. Walking through the options shows where the gaps are.
- The Authorization Code grant is for the "user logs in to a client app" case. The access token has the user as
sub. From the resource server's view, the call looks like the user calling directly. The client is invisible at authorization time. If an agent uses this token, the resource server cannot tell the user from the agent. There is no audit trail for the agent at all. - The Client Credentials grant is for service-to-service calls. The token has the service as
sub. There is no user in the picture. If an agent gets a token this way, it acts on its own authority, with no record of user consent. That is the wrong model. The user owns the data. The agent should only act because the user said so. - Token exchange (RFC 8693) handles the case where service A needs to call service B while preserving the user's identity. It re-issues a token with the right audience and a narrower scope. It supports an
actclaim that names who is acting on the user's behalf. Microsoft's named "On-Behalf-Of" flow is one well-known implementation of this pattern. RFC 8693 even supports nestedactclaims, so chains like "agent A called agent B which called API foo" can be expressed today.
RFC 8693 gets close to what agents need. But it has two limits.
- RFC 8693 is a back-channel mechanism. It assumes the calling service already has a valid user token. There is no clean way to ask the user for fresh consent in a browser when an agent is the thing being granted access.
- Classic OBO assumes the calling service is forwarding the user's intent. The user clicked a button. The service is just propagating what the user already decided. AI agents do not work this way. An agent makes its own decisions based on context. It is not forwarding intent. It is creating intent. The auth system needs to know that and capture it.
Microsoft Entra Agent ID OBO addresses the second limit. It extends Microsoft's OBO flow with agent-specific claims (appid, xms_act_fct, and others) so receiving services can tell that the caller is an agent, not just another service. It is in production today and works well within the Microsoft stack. But it is vendor-specific, and it still relies on the back-channel pattern for the underlying exchange.
What is missing is a vendor-neutral, front-channel flow that asks the user for explicit consent to delegate to a named agent. That is what draft-oauth-ai-agents-on-behalf-of-user proposes. The draft, titled "OAuth 2.0 Extension: On-Behalf-Of User Authorization for AI Agents," extends the authorization code flow with two parameters that carry the agent's identity through the consent screen and into the access token. Users see the agent on the consent screen. The agent authenticates itself at the token endpoint. The resulting token names the user, the client, and the agent.
!!Note that this is an Internet-Draft (revision -02, August 2025), not yet adopted by the OAuth working group. Specifics may change, but the core ideas (front-channel consent, a named actor, an act claim) are likely to persist.!!
These approaches are not mutually exclusive. A production system might use this flow to get the user's first consent for an agent, then fall back to RFC 8693 token exchange when that agent needs to call other services downstream.
The roles
Five parties take part in the new flow. Four are familiar from regular OAuth. One is new.
- The user is the resource owner. They own the protected data.
- The client is the app that talks to the user, the agent, and the auth server. It runs the flow.
- The actor is the agent. This is the new piece. The actor is the AI agent that wants to act for the user.
- The authorization server authenticates the user, runs the consent screen, and issues tokens.
- The resource server holds the protected data. In agent systems, this is often an MCP server or another agent's API.
The split between client and actor is the key idea. The client is the app the user trusts. The actor is the agent the user is delegating to. They are not the same thing. The flow makes this distinction explicit.
The new parameters
The draft adds two parameters to the existing Authorization Code flow.
-
requested_actorgoes on the authorization request. It is the unique identifier of the agent the user is being asked to delegate to. The auth server uses this to show the agent's name on the consent screen. actor_tokengoes on the token request. It is a security token that proves the agent is who it says it is. Usually a JWT, with asubclaim that matches therequested_actorvalue. The auth server checks that these match before issuing an access token.
Together, these parameters bind three identities to a single token:
- The user who consented.
- The client that ran the flow.
- The actor that will act.
How the On-Behalf-Of flow works step by step
Here is what happens when an agent needs to act for a user.
- The agent tells the client what it wants to do. It hands over its identifier (the actor ID).
- The client tries the action. It calls the resource server with whatever token it has.
- The resource server rejects the call. It sends back a 401 or 403 with a
WWW-Authenticateheader. This is the challenge. - The client redirects the user to the auth server. The URL has the usual OAuth parameters plus
requested_actor=<actor_id>. PKCE is required. - The user logs in. The auth server shows a consent screen. The screen names the client, the agent, and the scopes.
- The user approves. The auth server returns an authorization code through the redirect.
- The client calls the token endpoint. It sends the code, the PKCE verifier, and the
actor_token. - The auth server checks everything. The code must be valid. The PKCE verifier must match. The
subof theactor_tokenmust match therequested_actorthe user consented to. - The auth server issues an access token. The token is a JWT. It carries claims for the user, the client, and the agent.
- The client retries the action with the new token.
- The resource server validates the token, checks the delegation claims, and serves the data.

The sequence looks like a normal authorization code grant with PKCE. The new bits are requested_actor going in, actor_token coming back, and the act claim on the way out.
What the access token looks like
The draft says the access token should be a JWT, following RFC 9068. The interesting field is the act claim.
A decoded payload looks like this:
!!Need to inspect a token? Use the WorkOS JWT Debugger to decode and inspect your JWTs directly in the browser. It's a quick way to verify your token's iss, aud, sub, and other claims while debugging.!!
Pay attention to these claims:
subis the user. They own the data.azpis the client. They ran the flow.act.subis the agent. They will perform the action.
A resource server can log all three. If something goes wrong, the audit trail shows exactly which agent did what for which user through which client. Today, an action taken by an agent and an action taken by the user appear identical in the logs. With the act claim, the same operation produces a record that a compliance team or incident responder can actually use. "Show me every action agent X took for user Y last week" becomes a query, not a guess.
Security best practices
A few things deserve close attention.
- PKCE is required. The draft is firm on this. Agent code paths often run in environments where redirects are easy to intercept. PKCE blocks code interception.
- The auth server must bind the code to the actor. When it issues the authorization code, the server must remember which actor the user consented to. At token time, it must check that the
actor_tokenmatches. Without this binding, one agent could trade in a code that another agent's user approved. - Authority reduces, not amplifies. A common worry with delegation flows is whether an agent can end up with more power than the user. The answer is no, by design. The output of any OBO exchange is the intersection of three things: what the user can do, what the agent can do, and what the target API will accept. If the user lacks a permission, the agent cannot get it through delegation. If the target API does not trust the agent, the exchange fails. Each hop in a chain produces a more constrained token, not a less constrained one.
- Mind the capability gap. Agents and users do not always have the same capabilities. An agent may be allowed to call rate-limited APIs that users cannot reach. A user may have admin powers an agent should never exercise. The flow lets you enforce this. The auth server can refuse to issue a token that combines a user identity with an agent that is not approved for the requested scopes, or with a user who is not allowed to delegate to this agent at all.
- Consent screens must name the agent. A user clicking through a consent screen needs to know which agent is being granted access. "This app wants to read your email" is not enough. "This app wants to let the Finance Assistant agent read your email" is the right level.
- Authorization codes must be single-use and short-lived. This is true in regular OAuth, but it matters more here. The code carries a delegation grant. Replay would let an attacker hijack a delegation the user thought was settled.
On-Behalf-Of and MCP
Let's see how On-Behalf-Of fits into MCP. The role mapping is clean: the MCP endpoint is the resource server, the MCP client runtime is the agent, the host application (a chat app, an IDE, an internal tool) is the OAuth client, and the human is the user.
MCP already requires OAuth 2.1 for remote servers, and uses WWW-Authenticate challenges when a token lacks the right scopes. That existing pattern is what the On-Behalf-Of draft would build on. The same challenge-and-grant flow an MCP server runs today extends naturally to ask for tokens that name the agent.
The value for builders is identity an MCP server can trust. Today, the server cannot distinguish a user clicking buttons in their host app from an agent reasoning autonomously over the same user's data. A token with an act claim closes that gap. What the server does with the signal (different treatment, audit, narrower scopes) is up to the implementer.
What is still open
The draft is informational and still in progress. A few things are not yet settled.
- Actor token bootstrapping is not in scope. The draft does not say how agents get their actor tokens in the first place. Common options include having agents authenticate to the auth server through client credentials, or using a workload identity system like SPIFFE to issue agent identities at runtime. The right choice depends on the deployment.
- Multi-hop delegation is partially solved. The new draft only covers one hop, from user to agent. If agent A needs to invoke agent B, the draft does not say how. RFC 8693 already supports nested
actclaims that capture chains like "agent A called agent B which called API foo," so you can express the chain today. But RFC 8693 treats prior actors as informational, not enforced. Other IETF drafts are working on the enforcement piece, including drafts on attenuating tokens and cryptographically verifiable actor chains. The full picture is still being assembled. - Revocation patterns for delegated tokens are not detailed. If a user wants to revoke an agent without revoking themselves, the auth server needs a way to track that. The draft leaves this open.
- The draft is not the only proposal. Adjacent IETF drafts tackle related problems. draft-oauth-transaction-tokens-for-agents extends the OAuth Transaction Tokens framework with
actorandprincipalfields to propagate agent context through a service call graph. draft-embesozzi-oauth-agent-native-authorization handles authentication challenges (TOTP, WebAuthn) when a human is interacting through an agent. Both are newer than the draft we covered and solve different pieces of the agent identity puzzle.
Wrapping up
The On-Behalf-Of draft is a small extension, but it tackles a real problem.
The draft proposes a clear way for OAuth to express "this user said this agent can do this thing." That separation matters. It gives users meaningful consent. It gives resource servers an audit trail. It gives builders a path that does not depend on impersonation hacks or vendor-specific extensions.
The spec is not final and may change. But the direction is right, and the core ideas are likely to land somewhere in the OAuth ecosystem in the next year or two. If you are building agent systems, this draft is worth tracking and designing toward.
Authenticate your AI agents with WorkOS
WorkOS AuthKit is an OAuth 2.1-compatible authorization server that gives AI agents access to your app through standards-compliant flows. PKCE, dynamic client registration, granular scopes, and JWT verification all work out of the box, so the agent identity claims described in this article slot in cleanly when you need them.
For agentic workflows, WorkOS Pipes lets you grant agents time-limited access to OAuth connections, scope tokens to specific tools, and enforce permissions so agents can only invoke what they have been authorized to use. Combined with enterprise SSO, directory sync, and audit logs, you get the delegation chain visibility that On-Behalf-Of flows are meant to provide.