Delegation chain explorer

An orchestrator delegates to a sub-agent with token exchange

Alex asks an orchestrator agent for a report. The orchestrator holds a token for the documents API in Alex's name and hands part of the work to a research sub-agent. Each hop exchanges the token it holds for a narrower one with an act claim, so the API can see the whole chain of who acted for whom, and no hop can do more than the one before it.

Misconfigurationmay_act not checked

The authorization server exchanges the delegated token for any actor that presents it, without checking that the subject token's may_act names that actor. Whoever obtains the orchestrator's delegated token can extend the chain in Alex's name.

2 steps changed1 step removedAgainst 4.4. may_act (Authorized Actor) ClaimOAuth 2.0 Token Exchange rfc

The chain, step by step

AlexUser
Orchestrator agentAgent
auth.docs.exampleAuthorization server
Research sub-agentAgent
Documents APIResource
  1. Step 1: Alex to Orchestrator agent

    Write me a report from this quarter's documents

    The orchestrator already holds an access token for the documents API that Alex obtained through the usual authorization code flow.

    1.1. Delegation vs. Impersonation SemanticsOAuth 2.0 Token Exchange rfc

    Alex's access token held by the orchestratortyp at+jwt · alg ES256 · kid docs-2026

    iss
    https://auth.docs.example
    sub
    alex
    aud
    https://api.docs.example
    client_id
    orchestrator
    scope
    docs:read docs:write
    exp
    1790000000
    iat
    1789996400
    jti
    a1

    Unchanged since the previous token in this chain.

  2. Step 2: Orchestrator agent to auth.docs.example

    POST /token: grant_type=token-exchange, subject_token=<Alex's token>, actor_token=<orchestrator credential>, audience=https://api.docs.example, scope=docs:read

    Delegation, not impersonation: the orchestrator identifies itself with an actor token and asks for less than it holds.

    2.1. RequestOAuth 2.0 Token Exchange rfc

  3. Step 3: auth.docs.example to Orchestrator agent

    Delegated token: sub=alex, act.sub=orchestrator, scope=docs:read

    4.1. act (Actor) ClaimOAuth 2.0 Token Exchange rfc

    Delegated token for the orchestratortyp at+jwt · alg ES256 · kid docs-2026

    iss
    https://auth.docs.example
    sub
    alex
    aud
    https://api.docs.example
    client_id
    orchestrator
    scopechanged
    docs:read
    actadded
    {
      "sub": "orchestrator"
    }
    may_actadded
    {
      "sub": "research-subagent"
    }
    expchanged
    1789998200
    iatchanged
    1789996500
    jtichanged
    a2

    6 claims differ from the previous token in this chain. may_act says which party the subject allows to act on this token next; the authorization server checks it on the following exchange.

  4. Step 4: Orchestrator agent to Research sub-agent

    Task: summarise the quarter's documents; here is the delegated token to exchange

    The sub-agent does not present this token to the API. It is the subject token for the sub-agent's own exchange.

    1.1. Delegation vs. Impersonation SemanticsOAuth 2.0 Token Exchange rfc

    Delegated token, handed to the sub-agenttyp at+jwt · alg ES256 · kid docs-2026

    iss
    https://auth.docs.example
    sub
    alex
    aud
    https://api.docs.example
    client_id
    orchestrator
    scope
    docs:read
    act
    {
      "sub": "orchestrator"
    }
    may_act
    {
      "sub": "research-subagent"
    }
    exp
    1789998200
    iat
    1789996500
    jti
    a2

    Unchanged since the previous token in this chain.

  5. Step 5: Research sub-agent to auth.docs.examplereplaces "second-exchange"

    POST /token: grant_type=token-exchange, subject_token=<delegated token>, actor_token=<credential of an agent the token never authorised>

    2.1. RequestOAuth 2.0 Token Exchange rfc

  6. Step 6: auth.docs.example to itselfremoved by the toggle

    Check may_act on the subject token names the actor; keep scope within the subject token's

    The chain can only grow by parties the previous token authorised, and never wider.

    4.4. may_act (Authorized Actor) ClaimOAuth 2.0 Token Exchange rfc

  7. Step 7: auth.docs.example to Research sub-agentreplaces "second-delegated"

    Delegated token with an actor the subject never allowed

    4.1. act (Actor) ClaimOAuth 2.0 Token Exchange rfc

    Delegated token for an unauthorised actortyp at+jwt · alg ES256 · kid docs-2026

    iss
    https://auth.docs.example
    sub
    alex
    aud
    https://api.docs.example
    client_idchanged
    stranger-agent
    scope
    docs:read
    actchanged
    {
      "sub": "stranger-agent",
      "act": {
        "sub": "orchestrator"
      }
    }
    expchanged
    1789997900
    iatchanged
    1789996600
    jtichanged
    a4
    may_actremoved
    no longer in the token

    6 claims differ from the previous token in this chain.

  8. Step 8: Research sub-agent to Documents API

    GET /documents?quarter=2026-Q3 with Authorization: Bearer <delegated token>

    4. Validating JWT Access TokensJSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens rfc

    Delegated token as presentedtyp at+jwt · alg ES256 · kid docs-2026

    iss
    https://auth.docs.example
    sub
    alex
    aud
    https://api.docs.example
    client_idchanged
    research-subagent
    scope
    docs:read
    actchanged
    {
      "sub": "research-subagent",
      "act": {
        "sub": "orchestrator"
      }
    }
    exp
    1789997900
    iat
    1789996600
    jtichanged
    a3

    3 claims differ from the previous token in this chain.

  9. Step 9: Documents API to itself

    Validate signature, iss, aud and exp; enforce docs:read; log sub and the act chain

    The audit record says the sub-agent read documents for Alex by way of the orchestrator, and the API can refuse actors it does not expect.

    4.1. act (Actor) ClaimOAuth 2.0 Token Exchange rfc

  10. Step 10: Documents API to Research sub-agent

    200 with the documents

    4. Validating JWT Access TokensJSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens rfc

Requirements this chain exercises