Transaction Tokens

when an external endpoint accepts a request, it trades the caller's credential for a short-lived signed JWT that every internal workload in the call chain forwards unchanged and verifies, so the user and request context cannot be lost or altered on the way.

Where it stands
WG last call or write-up
Official text
draft-ietf-oauth-transaction-tokens-11
2026-08-21
Documented support
1
Activity
5 signals in 90 days

Explainer source on GitHub

When you reach for it

  • Internal workloads that can be invoked without a valid external transaction: a Txn-Token bound to one transaction, with a txn id and a short exp, proves that a real external request started the call chain (Section 1, Section 7).
  • Impersonation or parameter tampering between microservices: the subject and authorization details sit in signed sub, scope and tctx claims fixed by the Txn-Token Service at issuance, so no hop can rewrite them (Section 1, Section 9.2).
  • Stolen OAuth access tokens spreading through the mesh: the external access token stays at the edge; the Txn-Token MUST NOT contain it, and a Txn-Token MUST NOT be used as an access token (Section 13.4, Section 13.13).
  • Internally initiated work with no inbound token, such as a scheduled job: the workload presents a self-signed JWT as subject_token and still gets a Txn-Token for the chain (Section 5.1, Section 8.2, Section 11.2.1).
Diagram
flowchart LR
    A["API gateway receives a request with an access token"] -->|"forwards the access token or nothing"| B["Internal services cannot verify who asked or what was authorized, and a leaked token works anywhere"]
    A -->|"Txn-Token"| C["One short-lived signed JWT with sub, scope, txn and tctx travels the whole call chain"]

The problem it solves

An external API request fans out into a chain of internal workload calls, and each workload usually sees only the previous hop. That opens the door to invoking workloads without a valid transaction, impersonating users or workloads, modifying parameters mid-chain, and stealing the access tokens that carry authorization context. Txn-Tokens fix the identity, authorization context and request context in a short-lived signed JWT bound to the transaction and carried through the call chain, so every downstream workload applies its own authorization decision to the same immutable facts (Section 1, Section 4).

How it works

Diagram
sequenceDiagram
    participant X as External client
    participant G as External Endpoint (gateway)
    participant T as Txn-Token Service
    participant A as Workload A
    participant B as Workload B
    X->>G: request with OAuth access token
    G->>T: POST /token grant_type=token-exchange, requested_token_type=txn_token, audience=trust domain, scope, subject_token, subject_token_type, request_context, request_details
    T->>T: authenticate requester, validate subject_token, set iat aud exp txn sub scope req_wl tctx rctx
    T-->>G: access_token=Txn-Token, token_type=N_A, issued_token_type=txn_token
    G->>A: call with Txn-Token header
    A->>A: verify signature, aud is my trust domain, not expired
    A->>B: call with the same Txn-Token header, unmodified
    B-->>A: response
    A-->>G: response
    G-->>X: response

The external endpoint sends an RFC 8693 token exchange request to the Txn-Token Service with requested_token_type=urn:ietf:params:oauth:token-type:txn_token, the trust domain name in audience, the intended purpose in scope, the incoming credential as subject_token, and the RECOMMENDED request_context and request_details objects. The service mints a JWT with typ txntoken+jwt and the claims iat, aud, exp, txn, sub, scope, req_wl, plus tctx for immutable authorization details and rctx for the request environment. Every workload puts the token in the Txn-Token HTTP header, verifies it on receipt, and passes it on exactly as received (Section 9.1, Section 9.2, Section 11.1, Section 12).

What the spec requires

  • Each trust domain MUST have exactly one logical Txn-Token Service, which profiles the RFC 8693 token exchange endpoint (Section 3, Section 10).
  • The JWT header typ MUST be txntoken+jwt; iat, aud, exp, txn, sub, scope and req_wl are REQUIRED, tctx and rctx are RECOMMENDED, iss is OPTIONAL, and recipients MUST ignore claims they do not understand (Section 9.1, Section 9.2).
  • In the request, grant_type MUST be urn:ietf:params:oauth:grant-type:token-exchange, audience MUST be the trust domain name, requested_token_type MUST be urn:ietf:params:oauth:token-type:txn_token, and scope is REQUIRED (Section 11.1).
  • The response token_type MUST be N_A, access_token MUST be the Txn-Token, issued_token_type MUST be the txn_token URN, and the response MUST NOT include a refresh token (Section 11.4).
  • The requesting workload and the Txn-Token Service MUST authenticate each other (Section 11.5).
  • A workload calling another over HTTP MUST send exactly one Txn-Token in the Txn-Token header and MUST NOT use the Authorization header for it; receivers MUST verify the signature, that aud is their trust domain and that the token is not expired, and MUST forward it unmodified (Section 12, Section 12.1, Section 12.2).

Watch out

  • Txn-Tokens are not replay-resistant, so lifetimes MUST stay short, on the order of minutes or less, and the service MUST NOT issue one when the presented credential has already expired (Section 6, Section 13.1).
  • Refresh tokens MUST NOT be used to request Txn-Tokens, and the presented access token MUST NOT be embedded in the Txn-Token (Section 13.3, Section 13.4).
  • The requested scope MUST be equal to or narrower than the scope of the subject token; if that scope cannot be determined the request MUST be rejected rather than treated as unconstrained (Section 13.6, Section 13.14).
  • A Txn-Token MUST NOT be used to authenticate a workload and MUST NOT be used as an OAuth access token (Section 13.12, Section 13.13).
  • Replacement tokens issued from a Txn-Token MUST NOT expand what is permitted, MUST NOT change txn, sub or aud, and MUST NOT be issued from an expired token (Section 13.15).
  • Complete Txn-Tokens MUST NOT be logged verbatim; log a hash or the payload without the signature (Section 15.2).

Sources

How it relates to other specs

Relations diagram
flowchart LR
  s_txn_tokens["Transaction Tokens"]
  s_token_exchange["Token Exchange"]
  style s_txn_tokens stroke-width:3px
  s_txn_tokens -->|Builds on| s_token_exchange

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.

Products, identity providers and services

  • IBM Verify (Identity provider): Issues transaction tokens based on draft-ietf-oauth-transaction-tokens source (verified 2026-11-11)

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

    The evidence-binding authors will narrow a claim about suspended prior actors so it no longer conflicts with RFC 8693 Section 4.1.

    New I-D: draft-thaha-wimse-agent-evidence-binding-00 (evidence binding for AIMS audit)

    Read the explanation

    Shameer accepts Mikhail's two corrections. The statement that a Serving Party cannot refuse a call because a prior actor is suspended was too broad, because RFC 8693 Section 4.1 only rules out using nested act claims for that decision, not separately verified delegation tokens. The wording becomes: cannot refuse a call on the basis of the nested act claims because a prior actor has since been suspended. The phrase about history being neither complete nor evidence is replaced with: does not by itself establish that it is complete, or that any hop held or narrowed authority. Both edits will go into the next revisions of the SCITT draft and the Evidence Binding draft. No draft text was posted in this message.

    • A Serving Party deciding whether it may deny a call based on a suspended prior actor, using verified delegation tokens rather than nested act claims.
    • Related in OAuth WG: draft-ietf-oauth-transaction-tokens. Weak link only: both deal with carrying delegation context across hops, but the material does not reference it.
  • 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

    AAT, Asor and Cred -02 authors agree a child's lower del_max_depth must be honoured, and compare constraints before IETF 127.

    AAT -02 announcement (2 new messages)

    Read the explanation

    Kieran agrees that the effective maximum depth at any hop is the lowest del_max_depth on the path, and that this cap is separate from the question of the leaf at the maximum (AAT J.10.f accepts a leaf at del_depth equal to the root maximum, Asor -03 rejects it). Rob Zagarella asks the comparison of the three drafts to record whether each can bind a leaf to a digest of one exact request; Kieran says Cred -02 cannot express that in the token today, and its Section 5.5 takes the chain format by reference so its entry for off-DS verification is provisional. Rob also asks that the AAT Section 9.8 revocation freshness bound be stated in the same terms as Cred -02 Section 7. Niki holds a side meeting on 16 November in San Francisco.

    • Implementers of attenuating delegation tokens who need to know whether a leaf at the maximum depth is accepted.
    • Human-approval flows where an approval must bind to one exact action such as a payee and amount.
    • Related in OAuth WG: draft-ietf-oauth-transaction-tokens. Not referenced in the material; omit if unsure.
  • Minor or unclearIETF WIMSE

    Chairs say a competing cross-domain transaction token proposal may ask questions at the IETF 127 joint session but may not co-present

    OAuth IETF 127 Call for Agenda Items

    Read the explanation

    This is a short reply from Sean to Yuan, quoting an earlier thread. Yuan had asked for five minutes at the joint WIMSE/OAuth session to present draft-liu-oauth-cross-domain-txn-token, which targets the same use case as the Cross-Domain Transaction Tokens item already on the agenda. Sean says that after talking with Pieter and George, Yuan is welcome to ask questions but co-presenting is not an option for now. The quoted call for agenda items says the OAuth chairs requested two two-hour slots plus a joint WIMSE/OAuth session. It also says items with demonstrated interest from several parties get priority, and gives 2 November 2026 as the draft submission cut-off. No protocol text changed.

    • Related in OAuth WG: draft-ietf-oauth-transaction-tokens. The joint session item concerns transaction tokens extended across domains, and the competing draft targets the same use case.
  • DiscussionIETF WIMSE

    Rob Zagarella commented on Cred delegation -02: keep human-approval evidence separate in a user-minted root, and specify suspend/restore semantics.

    draft-sweeney-wimse-credential-delegation-02

    Read the explanation

    The thread carries Kieran Sweeney's -02 announcement. The draft is a profile where a Delegation Server holds user-deposited credentials and agents exercise them by proxy under a delegation token. Main changes are a sub-delegation exchange, rank order in the token, cumulative bounds (max_lifetime, max_subtree) with the DS as single writer, a chain-verifiable profile adopting draft-asor-wimse-agent-delegation-chain's agent_delegation format, and revocation framed as invalidation, not closure. Zagarella's reply, the new message, suggests that -03 distinguish who minted a root from evidence of natural-person approval, recording only method and assurance. It also asks Section 7 to say what a verifier sees for actions during a suspension and whether a restored delegation is the same grant, with the 1-hour cap presented as a bound on exposure.

    • An agent platform that lets users deposit upstream credentials and delegate to agents without exposing them.
    • A verifier away from the Delegation Server needs a fixed place to check human-approval evidence for a user-minted root.
    • Related in OAuth WG: draft-ietf-oauth-transaction-tokens. Both carry delegated authority across call chains, but the material does not link them explicitly; weak connection.