Consider a web API that needs to call a second API, and the second API needs to know whose data it is accessing. The obvious shortcut is to just forward the user's original access token to the downstream service. Do not do this. Relaying a token to a party it was not issued for breaks the trust boundary the token was scoped to in the first place. The middle-tier service needs its own token, one that still carries the user's identity, without reusing the user's actual credential.
This is the problem that On-Behalf-Of (OBO) flows address. But it is worth being precise about what the On-Behalf-Of name actually refers to, because the confusion that follows is not really about competing flows. On-Behalf-Of is an architectural pattern: a label for the shape of this problem, not a protocol for solving it. OAuth 2.0 Token Exchange (RFC 8693) is the IETF-ratified standard eventually built to implement that pattern in an interoperable way. Microsoft's own "OBO" flow is a third thing again: a specific, non-standardized implementation of the pattern that predates the standard and is not compliant with it.
Keep those three apart: the pattern, the standard, and a vendor's implementation. Most of the confusion in this space will then resolve on its own. Including the part where RFC 8693 implementations are named "On-Behalf-Of" and people assume that means they are all doing what Microsoft does.
Let's work through the pattern first, then the one legacy implementation worth understanding on its own terms, then the standard that formalized it, then the part neither one was designed to answer: explicit delegation from the user to the downstream service or agent.
The Problem: A Middle-Tier Service Needs to Act as the User
Three actors show up in every version of this scenario:
- a client, which is the application the user is interacting with,
- a middle-tier API, i.e., a service that received the user's request and now needs data from somewhere else,
- a downstream API: the service that actually holds that data.
The client authenticated once and got a token for the middle-tier API. Now the middle-tier API needs a token for the downstream API, and it needs that token to represent the user, not itself.
This rules out two tempting shortcuts:
- Forwarding the client's original token downstream is unsafe, since that token's audience is the middle-tier API, not the downstream one.
- Having the middle-tier API call the downstream API with its own service credentials solves the audience problem but creates a worse one: the downstream API can no longer tell whether the actual user is authorized to see this data, because all it sees is the middle tier's own identity.
What is needed is delegation: a new token that identifies the user as the subject of the request, while also recording that the middle-tier API is the one making the call. On-Behalf-Of is the name for exactly that pattern.
OBO as the Pattern Implementation
Microsoft's implementation (the one most developers mean when they say "OBO") is the oldest widely-deployed answer to the problem above, and it's worth understanding on its own terms, since a lot of production systems still run on it. It follows a fixed sequence, as shown in this diagram:

Following the numbered steps:
- The client authenticates and requests an access token.
- The token endpoint issues Token A, scoped to the middle-tier API.
- The client calls the middle-tier API using Token A.
- The middle-tier API authenticates itself to the token endpoint and requests a new token for the downstream API.
- The token endpoint validates the middle-tier API's own credentials and Token A
- The token endpoint issues Token B, scoped to the downstream API.
- The middle-tier API calls the downstream API with Token B.
- The downstream API responds
- The middle-tier API returns the result to the client.
In Microsoft's implementation, a minimal request looks something like this (shared-secret variant):
POST /oauth2/v2.0/token HTTP/1.1 Host: login.microsoftonline.com Content-Type: application/x-www-form-urlencoded grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer &client_id={middle-tier-api-client-id} &client_secret={middle-tier-api-client-secret} &assertion={token-a} &scope=https://downstream-api.example.com/.default &requested_token_use=on_behalf_of
Two details matter here:
- First, this implementation only works for user principals. If the original token represents an app calling with its own client credentials rather than a signed-in user, there is no user identity to carry forward, and this flow is not the right tool (client credentials chaining is).
- Second, Token B should never be relayed back to the client. It was issued for the downstream API's audience, and sending it anywhere else turns a scoped delegation into exactly the kind of token-forwarding problem the pattern exists to prevent.
The most common place this shows up in practice is a chain of calls into Microsoft Graph or another Entra-protected resource: a web app calls its own backend, the backend needs Graph data scoped to the signed-in user, and this flow produces the Graph-scoped token without ever exposing the user's original session token to the backend's downstream dependencies.
A less obvious but genuinely useful variant: this implementation's nonstandard extension for minting SAML assertions, which some SSO integrations still expect instead of an OAuth 2.0 access token. Rather than running a parallel SAML identity provider alongside Entra ID, a service can exchange a user's OAuth token for a SAML assertion scoped to the legacy downstream service. That bridges two protocol generations without forcing a full migration. That is a legacy-protocol bridge specific to this implementation, not something a standardized approach needs to replicate, since most RFC 8693 deployments are already OAuth2-to-OAuth2.
Token Exchange: The Standard That Formalizes the Pattern
OAuth 2.0 Token Exchange is the IETF-ratified, vendor-neutral protocol for the same delegation pattern described above. It defines its own grant type (grant_type=urn:ietf:params:oauth:grant-type:token-exchange). It uses a subject_token to carry the user's identity forward and an optional actor_token to record who is making the call. Unlike Microsoft's implementation, it also specifies an explicit, chainable act claim: each hop in a multi-service call can be nested inside the previous one, so a downstream service can see the full path a request traveled.
We will not go into the details of how Token Exchange works here. For the full tour of Auth0's RFC 8693 implementation, take a look at The Many Faces of OAuth 2.0 Token Exchange and A Developer's Guide to Flexible Token Exchange on Auth0 blog posts, and read the documentation.
The point that matters here is narrower: Token Exchange is nit a rival to On-Behalf-Of. It is what the pattern looks like once someone wrote it down as an interoperable standard.
Who Implements What
The pattern now has two implementations, and which one you can reach for depends on your identity provider: Auth0, Okta, and other identity products implement RFC 8693 directly. Microsoft Entra ID and other products do nit. They still require the older, vendor-specific jwt-bearer grant or use other custom implementations instead.
This is also where the naming confusion actually lives. Several vendors, Auth0 included, have built an RFC 8693 implementation and named it "On-Behalf-Of." Auth0's On-Behalf-Of (OBO) Token Exchange uses grant_type=urn:ietf:params:oauth:grant-type:token-exchange, the actual RFC 8693 grant, nesting the act claim up to five levels deep. That's not a second, competing meaning of "OBO." It is the pattern's name attached to a standardized implementation of it, the same way Microsoft's flow is the pattern's name attached to a non-standardized one. Do nit assume which implementation you are reading about from the name alone. Check the actual grant_type in the vendor's documentation.
The practical decision rule survives all of this naming confusion intact: check what grant type your identity provider actually implements before assuming "On-Behalf-Of" describes one specific wire protocol.
What Is There for AI Agent Delegation?
Both the pattern and its standardized protocol assume a user token already exists to exchange. Neither one has a front-channel step where a user explicitly consents to a named agent acting on their behalf. The exchange happens entirely back-channel, between services that already trust each other, with no moment where the user sees "Agent X wants to act for you" and approves it specifically.
From the downstream service's point of view, the trail has traditionally looked the same whether a human, a cron job, or an autonomous agent made the call. That is starting to change on the audit side: Auth0's Agent as Principal feature (currently Early Access) lets a tenant register a persistent agent identity and surface it in the act claim during token exchange, so a resource server that opts in can tell which specific agent acted, not just which client called. But that is a back-channel improvement to the audit trail, not a front-channel one to consent. Delegation flows still were not designed to let a user approve 'this specific agent' before the fact, and audit trails still cannot tell you whether the agent was authorized to decide to act in the first place, only that it did.
A few individual IETF drafts aim to address this gap. Although none have reached consensus status yet, they are worth tracking:
- On-Behalf-Of User Authorization for AI Agents proposes a
requested_actorparameter at the authorization request and anactor_tokenparameter at the token request, so the specific agent's identity gets captured and consented to explicitly. It is front-channel, not back-channel, which is exactly the piece the existing pattern and standard both lack. - OAuth Actor Profile for Delegation standardizes the shape of the
actclaim across implementations, without dictating authorization policy on top of it. By the way, this is the draft currently adopted by Auth0 for its Agent as Principal feature. - Attenuating Authorization Tokens lets an agent derive a narrower token offline rather than round-tripping to an authorization server for every hop, trading central mediation for independence. That trade-off matters for multi-hop agent chains, i.e., for long chains of agents calling other agents. In this context, RFC 8693's synchronous exchange-per-hop model starts to add real latency.
Every one of these is an individual submission, not a working-group draft, and individual submissions carry no formal standing in the IETF process. Some of them have already expired or are about to expire at the time of writing. This is an area where the standards conversation is active but genuinely unsettled.
However, the IETF's WIMSE working group is now pursuing further standardization in this general space: the Workload Identity in a Multi System Environment (WIMSE) Architecture. It is early there as well, but it is the group to watch if you want to track where this settles.
MCP (Model Context Protocol) illustrates the practical shape of the problem. Map MCP's own actors onto OAuth 2.0 roles and the pattern is familiar: the MCP server is the resource server, the agent runtime is the client, the host application is the OAuth 2.0 client orchestrating the whole thing. But MCP itself treats authorization as optional and defers identity and delegation entirely to whatever external identity provider sits behind it. That mapping clarifies the protocol roles. It does nit tell you which user a given agent is acting for, and that remains the integrator's responsibility to solve, not something the spec hands you.
This is nit a problem unique to agents acting on a user's behalf, either. It rhymes with the confused deputy problem, the decades-old pattern where a privileged service gets tricked into misusing its own authority because it cannot tell a legitimate instruction from an injected one. Granting an agent broad delegated authority without a clear record of who authorized what just gives that old bug a new, more capable host.
What to Actually Do Today
Do not wait for the drafts above to stabilize. Here os what holds up regardless of how that standards conversation resolves:
- Reach for the standard, RFC 8693 Token Exchange, wherever your identity provider supports it. Fall back to the vendor-specific
jwt-bearerpattern only where the vendor forces it. Check the actual grant type in the docs, not just the feature name. - Log the
actclaim, or your provider's closest equivalent, on every delegated token, even if your downstream systems cannot natively consume it yet. Record actor, task, and approver at the application layer if the token itself will not carry it. Closing the audit gap in human-to-agent delegation covers concrete ways to do this with correlation IDs and approval checkpoints. - Issue one credential per agent per purpose. Never let an agent hold or relay a human's raw token. If you are building agent-facing infrastructure, a mechanism like Auth0's Token Vault is designed around exactly this constraint: managed, auditable, per-agent tokens for third-party API access. Auth0's Agent as Principal goes a step further by giving each agent its own registered identity with a stable ID, rather than relying on a shared M2M client or service account to stand in for every agent.
- Scope every delegated token to the specific task, not the full permission set of whatever credential is doing the calling. A narrower token limits the blast radius if an agent misbehaves or gets tricked into misusing its own authority.
- Build the audit trail now, not when the standards settle. Regulatory transparency requirements around automated decision-making are already in effect in a lot of jurisdictions, and historical logs cannot be reconstructed after the fact. Whatever you build today to answer "which agent did this, on whose authority" is worth more than a theoretically cleaner version you build next year.
The Pattern, the Standard, and the Identity Question
Consider the middle-tier API from the opening scenario. The primary question, how to invoke a downstream service using the user's identity without exposing their actual token, has been resolved for years. It began informally through patterns like On-Behalf-Of and is now standardized via RFC 8693 Token Exchange. The specific implementation depends on your identity provider, but the core design strategy is well established.
However, AI agents introduce new complexity. The question is no longer simply whether a service can act on behalf of a user, but whether a specific, designated agent has explicit user consent and an auditable record of that authorization. Neither OBO nor Token Exchange was designed for this capability, and the proposed drafts addressing it have not yet achieved IETF consensus. Until standards emerge, this gap must be managed through detailed logging, fine-grained scoping, and dedicated per-agent credentials.
About the author
Andrea Chiarelli
Principal Developer Advocate
I have over 20 years of experience as a software engineer and technical author. Throughout my career, I've used several programming languages and technologies for the projects I was involved in, ranging from C# to JavaScript, ASP.NET to Node.js, Angular to React, SOAP to REST APIs, etc.
In the last few years, I've been focusing on simplifying the developer experience with Identity and related topics, especially in the .NET ecosystem.
