Agentic Authentication & Authorization - Part 3: Delegation

Nov 14, 2026 min read

Part 2 gave the agent an identity. This part is about what happens when that agent acts for someone, and when the work passes through more services than the one the user consented to. The core tool is OAuth 2.0 Token Exchange (RFC 8693). Two OAuth working-group drafts extend it: one inside a trust domain, one across trust domains.

Delegation, not impersonation

RFC 8693 separates two things that are easy to blur.

  • Impersonation: A gets all of B’s rights within some context and is indistinguishable from B to anyone who receives the token. The RFC notes that this can be limited in scope or time, but the recipient still cannot tell A was involved.
  • Delegation: A keeps its own identity and acts on B’s behalf with some of B’s rights. The token identifies both parties. In the exchange request, subject_token represents B and actor_token represents A.

For agents, impersonation is the default mistake and delegation is the goal. An agent that holds the user’s own token is impersonating the user. An agent whose token says “Alice, acting through the finance assistant” is a delegate, and every system downstream can see both names.

Token exchange step by step

A token exchange is a normal call to the token endpoint with a special grant type. Here the payments MCP server, holding Alice’s token from the finance assistant, asks for a token to call the ledger API:

POST /token HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=eyJhbGciOi...
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&resource=https://ledger.example.com
&scope=postings:write
&requested_token_type=urn:ietf:params:oauth:token-type:access_token
ParameterRequiredWhat it does
grant_typeYesAlways urn:ietf:params:oauth:grant-type:token-exchange
subject_token, subject_token_typeYesThe party the new token is about: Alice
actor_token, actor_token_typeOptional (type required if the token is sent)The party receiving delegated rights, when it is not simply the authenticated client
resource / audienceOptionalWhere the new token will be used, as a URI or a logical name
scopeOptionalScopes for the target service
requested_token_typeOptionalThe kind of token wanted; the server decides if omitted

The response returns the new token in access_token (the name is historical; it need not be an OAuth access token), with issued_token_type, token_type and a recommended expires_in. RFC 8693 notes that a refresh token is usually not issued when one short-lived credential is exchanged for another.

The act and may_act claims

The delegation shows up in the issued token as an act claim. The outermost act is the current actor; nested act claims record earlier actors, deepest first. A decoded token for the ledger call might look like this:

{
  "iss": "https://as.example.com",
  "aud": "https://ledger.example.com",
  "sub": "alice@example.com",
  "scope": "postings:write",
  "exp": 1794670000,
  "act": {
    "sub": "https://payments-mcp.example.com",
    "act": {
      "sub": "https://agents.example.com/finance-assistant.json"
    }
  }
}

Two rules in RFC 8693 shape how you use this. First, access decisions should use only the top-level claims and the current actor; prior actors are informational only. The ledger can authorize “Alice via the payments server”, and keep the finance assistant in its logs. Second, may_act works the other way round. Placed in a subject token, it names who is allowed to act for the subject, and the authorization server can check it before issuing a delegated token. That is the standard hook for saying “only these agents may act for Alice”.

Actor chains across hops

Put the pieces together and a single request from Alice produces a different token at every hop. Each one is narrower than the last, and each still says whose authority it carries.

Each hop gets a new, narrower token that still names the userAlicethe userFinance assistantagent, MCP clientPayments MCP servertool, resource serverLedger APIdownstream servicePosting serviceinside the ledger's domain1. Alice delegates (authorization code + PKCE)Token for the payments MCP serversub: alice · client_id: finance-assistant · aud: payments-mcp2. The agent calls the toolSame token, sender-constrained with DPoPThe server checks aud = payments-mcp and never forwards it3. Token exchange for the ledger (RFC 8693)sub: alice · aud: ledger-api · scope: postings:writeact: payments-mcp, nested act: finance-assistant4. Transaction Token inside the ledger's domaintxn: unique ID · sub: alice · req_wl: ledger-apiaud: the trust domain · lives minutes · no refresh token
Each hop gets a new, narrower tokenthat still names the userAlicethe userFinance assistantagent, MCP clientPayments MCP servertool, resource serverLedger APIdownstream servicePosting serviceinside the ledger's domain1. Alice delegates(authorization code + PKCE)Token for the payments MCP serversub: alice · client_id: finance-assistant ·aud: payments-mcp2. The agent calls the toolSame token, sender-constrained with DPoPThe server checks aud = payments-mcp andnever forwards it3. Token exchange for the ledger(RFC 8693)sub: alice · aud: ledger-api ·scope: postings:writeact: payments-mcp, nested act:finance-assistant4. Transaction Token inside theledger's domaintxn: unique ID · sub: alice ·req_wl: ledger-apiaud: the trust domain · lives minutes ·no refresh token

Only step 1 involves Alice. From then on, each service asks for exactly what the next call needs, and the authorization server records who passed the authority along. The highlighted step is the one most deployments skip, by forwarding the token from step 1 instead.

Narrowing at every hop

Every exchange is a chance to give the next service less than the current one holds. Four levers, all in finished RFCs:

  • Audience. Name exactly one target with resource (RFC 8707) or audience (RFC 8693). A token for the ledger is useless at the CRM.
  • Scope. Ask only for what the next call needs. The authorization server should refuse anything broader than the subject token carries.
  • Lifetime. Short expires_in, and no refresh token for a credential that exists only to make one downstream call.
  • Structured grants. Where an action needs more than a scope string, such as an amount or a creditor, Rich Authorization Requests (RFC 9396) carry it as authorization_details that the authorization server shows the user at consent time.

The pattern to avoid is the opposite: one broad token at the start of the chain, passed or copied all the way down. Part 4 covers why MCP forbids that outright.

Inside one trust domain: Transaction Tokens

Once a request is inside your own infrastructure, it often fans out across many internal services. Exchanging an access token at every internal hop is heavy, and passing the external token around is worse. The OAuth working group’s Transaction Tokens draft (-11, July 2026, working-group consensus) fills this gap.

A Transaction Token is a short-lived signed JWT that carries user identity, workload identity and authorization context through a call chain within one trust domain. How it works:

  • One issuer per domain. Each trust domain has exactly one logical Transaction Token Service (TTS).
  • Obtained by token exchange. The edge workload calls the TTS with RFC 8693, setting requested_token_type to urn:ietf:params:oauth:token-type:txn_token and audience to the trust domain. Workload and TTS authenticate each other. The response has token_type N_A and no refresh token.
  • Claims. Required: iat, aud, exp, txn (a unique transaction ID), sub, scope and req_wl (the requesting workload). Recommended: tctx, immutable transaction details, and rctx, the request’s environment.
  • Minutes, not hours. Tokens should live for minutes or less.
  • Never outside the domain. A Transaction Token must not be accepted outside the trust domain named in aud.
  • Replacement narrows only. A service can trade a Transaction Token for a replacement with narrower scope or added context, but the TTS must not widen scope or change txn, sub or aud.

For agents, tctx is the useful part. Details fixed at the edge, such as “transfer 250 EUR to payee P”, travel with the request and cannot be altered by a service further down, even one that has been compromised. The IETF draft on AI agents (draft-ietf-wimse-aims) recommends exactly this: exchange the received access token for a Transaction Token to carry context along the chain.

Across trust domains: Identity and Authorization Chaining

When the next hop belongs to another organization, its authorization server will not accept your tokens. OAuth Identity and Authorization Chaining Across Domains (-17, in the RFC Editor queue) combines two existing RFCs to bridge the gap:

  1. The client in domain A discovers domain B’s authorization server, for example from B’s Protected Resource Metadata.
  2. It runs an RFC 8693 token exchange at its own authorization server, naming B’s server as resource or audience.
  3. Its authorization server returns a JWT authorization grant whose aud is B’s authorization server.
  4. The client presents that grant to B’s authorization server using the RFC 7523 jwt-bearer grant type.
  5. B’s server validates it and issues an access token for B’s resource.

The draft leaves the claim set to the two servers (“claims transcription”): they can map Alice’s identifier in A to her identifier in B, strip claims B does not need, and narrow scope. Its security section adds three rules worth adopting: B should not issue refresh tokens, since they could outlive Alice’s session in A; the grant is a bearer credential, so keep it short-lived and single-use; and A should check that the presenting client is actually allowed to use the subject token.

One gap matters for agents: the draft does not define how the actor chain crosses the boundary. It says nothing about act. If domain B needs to know an agent was involved, the two servers have to agree on how to carry it.

Agent-to-agent: what changes, and what is still open

When one agent calls another, nothing new is needed at the protocol level. The called agent is a protected resource; the caller gets a token for it and presents it. draft-ietf-wimse-aims describes it that way, with the calling agent in client_id and the principal it serves in sub, Transaction Tokens inside a domain and Identity Chaining across domains.

What changes is depth. Chains of agents get long, and three questions have no standard answer yet:

  • How far can authority travel? RFC 8693 records every prior actor but says access decisions should use only the current one. Nothing standard says “at most two hops” or “this agent may not re-delegate”. may_act lets the authorization server control who may act for a subject at each exchange, which is the closest standard hook today.
  • What did the user actually agree to? Consent happens once, at the top. Each hop narrows scope, but no standard ties a sub-agent’s request back to the user’s original intent. Transaction Token tctx carries fixed details within one domain; across domains, nothing does.
  • Can you rebuild the chain afterwards? draft-ietf-wimse-aims says operators should be able to reconstruct the full execution chain, including delegated authority and intermediate calls. That is a logging requirement, covered in Part 7, not something a token gives you on its own.

Many individual IETF drafts propose new delegation and actor-chain mechanisms for agents. None has working-group adoption for this purpose yet, and some have already expired. The safe path today is RFC 8693 delegation with act and may_act, Transaction Tokens inside a domain, and Identity Chaining across domains.

Standards status (November 2026)

StandardStatusUse it for
RFC 8693, Token ExchangeRFC (Jan 2020)Delegation with act and may_act
RFC 7523, JWT authorization grantsRFC (May 2015)Presenting a grant to another domain’s authorization server
RFC 8707, Resource IndicatorsRFCBinding each token to one audience
RFC 9396, Rich Authorization RequestsRFC (May 2023)Structured grants such as amounts and creditors
Transaction TokensOAuth WG draft -11, WG consensusContext through internal services in one trust domain
Identity and Authorization ChainingOAuth WG draft -17, RFC Editor queueHops across trust domains
AI Identity Management System (draft-ietf-wimse-aims)WIMSE WG draft -01, InformationalHow these pieces fit together for agents

Sources