Identity and Authorization Chaining

a client in trust domain A exchanges the token it holds for a JWT grant from A's authorization server, then presents that grant to domain B's authorization server for an access token, so the user's identity and authorization survive the domain crossing.

Where it stands
Approved, with the RFC Editor
Official text
draft-ietf-oauth-identity-chaining-17
2026-08-21
Documented support
0
Activity
4 signals in 90 days

Explainer source on GitHub

When you reach for it

  • A user's request spans on-premise and cloud workloads in different trust domains: each workload applies its own policy to the same user context instead of losing it at the boundary (Appendix A.1).
  • A CI system that needs external resources under another authorization server: the build identity, such as commit hash and repository, travels across domains inside the grant (Appendix A.2).
  • A partner dashboard requesting a home camera feed: the device company can verify on its own that a permitted user authorized the request, not just that a partner called (Appendix A.3).
  • Extending enterprise SSO to API access: a client exchanges the IdP's identity assertion for a grant that a SaaS authorization server trusting that IdP accepts, with no extra user interaction (Appendix A.4, Appendix A.5).
Diagram
flowchart LR
    A["Client in domain A holds a token issued by AS A"] -->|"forwards it to domain B"| B["AS B cannot verify it and has no record of the user or the granted scope"]
    A -->|"chaining"| C["JWT grant from AS A, exchanged at AS B for an access token with the user context"]

The problem it solves

A request can pass through resource servers in several trust domains, each with its own authorization server. Every protected resource along the way needs to know who the request was made for, what authorization was granted, and optionally which resource servers were called before. A token from domain A means nothing to domain B. The draft combines RFC 8693 Token Exchange inside domain A with the RFC 7523 JWT grant at domain B, so that a verifiable grant carries the context across one or more domain boundaries (Section 1, Section 2.1).

How it works

Diagram
sequenceDiagram
    participant C as Client (domain A)
    participant ASA as Authorization Server A
    participant ASB as Authorization Server B
    participant RS as Resource Server (domain B)
    C->>C: discover AS B, for example authorization_servers in protected resource metadata
    C->>ASA: POST /token grant_type=token-exchange, subject_token, subject_token_type, resource or audience = AS B, scope
    ASA-->>C: JWT authorization grant, aud = AS B, issued_token_type jwt, expires_in
    C->>ASB: POST /token grant_type=jwt-bearer, assertion=grant, scope or resource
    ASB->>ASB: validate per RFC 7523 Section 3, aud is this server, identify subject, apply policy
    ASB-->>C: access_token
    C->>RS: request with access token
    RS-->>C: response

The client first finds domain B's authorization server, for example from the authorization_servers field of RFC 9728 protected resource metadata (Section 2.2). It then sends a token exchange request to its own authorization server, naming domain B's server in resource or audience. The grant that comes back is a JWT whose aud is domain B's server; domain A may add, remove or rewrite claims on the way, for example mapping the subject identifier or dropping claims domain B does not need (Section 2.3, Section 2.5). The client presents the grant as assertion with grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer, domain B validates it as an RFC 7523 grant and returns an ordinary access token (Section 2.4).

What the spec requires

  • In the token exchange request, one of resource (the URI of domain B's authorization server) or audience (its logical name) is REQUIRED; scope names the scopes to include in the grant, if any (Section 2.3.1).
  • Domain A's authorization server MUST deny the request if it is invalid or if the resource or audience is unknown or unacceptable under its policy (Section 2.3.2).
  • The aud of the issued grant MUST identify domain B's authorization server; listing several is allowed but restricting it to one is RECOMMENDED (Section 2.3.3).
  • Domain B's authorization server MUST validate the grant per RFC 7523 Sections 3 and 3.1, aud MUST identify that server by token endpoint or issuer identifier, and the server MUST deny the request if it cannot identify the subject (Section 2.4.2).
  • The access token response is a standard RFC 6749 Section 5.1 response (Section 2.4.3).
  • The OPTIONAL metadata parameter identity_chaining_requested_token_types_supported lists token types that can be requested as requested_token_type; a type left out is not necessarily unsupported (Section 3).

Watch out

  • The grant is a bearer credential. Implementations must evaluate the replay risk; mitigations are short lifetimes, single use and client authentication at domain B (Section 5.5).
  • Domain B SHOULD NOT issue refresh tokens in this flow; the client resubmits the grant or gets a new one from domain A (Section 5.4).
  • Authorization servers should follow RFC 9700 (its Section 2.5 for client authentication) for client authentication and sender-constrained tokens; bearer tokens remain the predominant access token type (Section 5.1, Section 5.2).
  • When downscoping, authorization servers need to verify that the requested scopes are not higher privileged than those of the subject_token (Section 2.5).
  • Include only the minimum data in the grant, and keep privacy policies aligned across the two domains (Section 6).

Sources

How it relates to other specs

Relations diagram
flowchart LR
  s_identity_chaining["Identity and Authorization Chaining"]
  s_token_exchange["Token Exchange"]
  s_jwt_bearer["JWT Bearer Grant and Client Authentication"]
  s_id_jag["Identity Assertion JWT Authorization Grant"]
  style s_identity_chaining stroke-width:3px
  s_identity_chaining -->|Builds on| s_token_exchange
  s_identity_chaining -->|Builds on| s_jwt_bearer
  s_id_jag -->|Profiles| s_identity_chaining

Documented support

Adoption lists only support stated in official documentation (the vendor's or project's own, or a standards body's page naming it), and a weekly check confirms the cited phrase is still on that page. Experimental, alpha and beta support is counted separately as preview.

No sourced support entries collected yet. This says nothing about how widely it is used.

Activity

Revisions from the Datatracker, explanations from this site's daily runs, and mailing-list subjects naming the draft.

Explanations on this site

  • DiscussionIETF WIMSE

    An IETF 127 hackathon plan for WIMSE agent call chains drew proposed negative test scenarios centred on revocation and fail-closed checks.

    IETF 127 Hackathon: WIMSE interop scenarios for agent call chains (5 new messages)

    Read the explanation

    Alexander Pelov will run interop scenarios across independent implementations (SPIRE with experimental WIT-SVID, go-spiffe, Cofide's PoC and a Python implementation). The scenarios use workload-creds-03, wpt-02, http-signature-08, identifier-04, Txn-Tokens and identity chaining across two trust domains, with a shared transaction ID in logs. The normal path binds a Txn-Token to each hop's proof, and the Txn-Token never leaves its domain. Replies from Ben Le (draft-le-agent-passport) and Iman add cases: unreachable status list, revocation after delegation, widening delegation, cumulative limits across two services, request rewritten by a proxy and tool-description digest changes. Iman asks that logs distinguish confirmed revocation, expired status cache and unavailable status service, and that a revoked authorization blocks the operation before effect.

    sequenceDiagram
     participant A as Agent A (domain A)
     participant B as Agent B
     participant R as Receiving hop
     A->>B: delegate
     B->>R: first call
     R-->>B: accepted
     Note over A: A is revoked
     B->>R: next call
     R-->>B: rejected (fail closed)
    • An implementer of WIT/WPT or Txn-Tokens wanting shared negative test cases to compare against other implementations.
    • A deployer defining fail-closed policy when a status list is unreachable or a delegating agent is revoked mid-chain.
    • Related in OAuth WG: draft-ietf-oauth-transaction-tokens. The scenario binds a Txn-Token to each hop's proof and keeps it inside its domain.
    • Related in OAuth WG: draft-ietf-oauth-identity-chaining. Crossing to trust domain B uses identity chaining.
  • DiscussionIETF WIMSE

    AIMS delegation thread: the delegated subject may differ across trust domains if the transcription is in the signed record.

    Subject: AIMS-00: multi-hop delegation context across agent, tool and resource boundaries (2 new messages)

    Read the explanation

    Kieran Sweeney clarified that "sub preserved" means the same principal, not the same bytes. Within one trust domain the value stays identical at every hop (sub fixed, actor in client_id and act). Across a trust domain, transcription under identity chaining is acceptable if the transcribing party records old value, new value and its own identity in what it signs; an AS merely keeping the mapping is not enough for AIMS Section 11. Marc proposes two changes on PR #176 along those lines. Both sides also agree to move the freshness boundary to at-or-past, so the 21 boundary vectors and the 23 October wording change, and the case admitted at exactly S+L becomes refused.

    sequenceDiagram
     participant A as Domain A AS
     participant B as Domain B AS
     participant L as Signed audit record
     A->>B: token with sub value X
     B->>B: transcribe X to Y
     B->>L: record old X, new Y, own identity
     B->>B: issue token with sub Y
    • A deployment where an agent chain crosses trust domains via identity chaining and needs auditors to reconstruct the original user from records alone.
    • A verifier implementing the S+L revocation-admission bound that must decide whether an input exactly at its limit is accepted.
    • Related in OAuth WG: draft-ietf-oauth-identity-chaining. The cross-domain transcribed identifier is discussed as OAUTH-ID-CHAIN Section 2.5.
  • DiscussionIETF WIMSE

    Review of Cred delegation -02: user-issued roots, tally mode and revocation status are the open points for -03.

    draft-sweeney-wimse-credential-delegation-02 (2 new messages)

    Read the explanation

    Kieran's -02 announcement describes a Delegation Server (DS) that holds deposited user credentials and lets agents exercise them by proxy under a delegation token. It adds sub-delegation exchange (5.4.1), rank order in the token, delegation_constraints with max_lifetime and max_subtree written only by the DS, a chain-verifiable profile (5.5) adopting the Asor agent_delegation format unchanged, revocation text stating revoked_count is invalidation not closure, and ML-DSA. Caleb Dayton raises six points, including the claim remap for user-issued tokens, using the token's jti as root receipt, a mode marker for single-writer versus delegate-held tally, and a status mechanism when no DS exists. Kieran agrees to a per-key mode marker but cautions that a per-verifier tally does not bound the total across verifiers, and says -02 names no status mechanism for tokens the DS did not issue. Rob Zagarella suggests separating who issued a root from evidence a person approved it, and asks Section 7 to cover suspension and restoration.

    sequenceDiagram
     participant U as User
     participant DS as Delegation Server
     participant AG as Agent
     participant UP as Upstream resource
     U->>DS: deposit credential
     DS->>AG: delegation token
     AG->>DS: exercise under token
     DS->>UP: call with deposited credential
     DS->>AG: result and receipt
    • An agent platform where users deposit OAuth credentials with a proxy and agents never hold the upstream token.
    • A verifier away from the DS that must decide whether a cumulative budget has been exceeded.
    • Related in OAuth WG: draft-ietf-oauth-identity-chaining. Not named in the material; omit.
  • DiscussionIETF WIMSE

    Marc asks whether sub being preserved at every hop means the same value everywhere, even across trust domains.

    Subject: AIMS-00: multi-hop delegation context across agent, tool and resource boundaries

    Read the explanation

    Marc cites Kieran's statements that sub is the Principal at every hop and stays the original delegated subject. He asks whether preserved means the same sub value at every party, including after a hop crosses a trust domain and a party gets a transcribed identifier (OAUTH-ID-CHAIN, Section 2.5). The alternative is that each value refers to the same User and the issuing authorization server keeps the mapping for Section 11. He asks because Nik is proposing text for Section 10.10 on AIMS issues #88 and #90 in which the value may differ between parties, and that text should not conflict with Kieran's property. No answer is in this message.

    • A multi-domain agent deployment where a downstream authorization server issues a different identifier for the same user.
    • Related in OAuth WG: draft-ietf-oauth-identity-chaining. The message cites OAUTH-ID-CHAIN Section 2.5 for transcribed identifiers across trust domains.