Token Exchange

クライアントが手元のトークンをトークンエンドポイントに差し出し、別のトークンを受け取る仕組み。ユーザーに代わって別のサービスへ行くときや、あるサービスが別のサービスの代理で動くときに使う。

現在地
RFC として公開済み
公式本文
RFC 8693
公式に文書化された対応
3
動き
3 件の動き (90 日)

RFC を英日対訳で読む解説の元ファイル (GitHub)

どういうときに使うか

  • 呼び出し元のアイデンティティを保ったまま backend API を呼びたいリソースサーバー: 受け取った access token をそのまま転送する代わりに、backend 向けに scope を絞った短命のトークンへ交換する (Section 2.3)。
  • ユーザーの代理で動くサービスで、backend に両者を見せたい: delegation では sub にユーザーを残し、サービスを act claim に記録する。backend は「誰が誰のために」呼んでいるかを判別できる (Section 1.1, Appendix A.2)。
  • サービスがユーザーそのものとして振る舞う必要がある: impersonation ではユーザーだけを名指しするトークンを発行し、そのトークンの範囲では保持者と subject を区別しない (Section 1.1, Appendix A.1)。
  • 手元のものとは別の種類のトークンが要るクライアント: SAML assertion や ID token を JWT に交換する。たとえば別の認可サーバーで認可グラントとして使うための JWT。結果が access token でなければ token_type は N_A (Section 2.2.1, Section 3)。
図
flowchart LR
    A["サービス A が A 宛ての access token を持っている"] -->|"そのまま B に転送"| B["B は自分宛てでないトークンを受け取り、誰が動いているかの記録もない"]
    A -->|"認可サーバーで交換"| C["B 向けの短命トークン、sub と任意の act claim 付き"]

解決する問題

あるサービスが、自分を audience とする access token 付きのリクエストを受け取る。そこから第二のサービスを呼ぶには、第二のサービスが受け付けるトークンが要る。元のトークンを横流しすると、第二のサービスは自分宛てに発行されていない credential を受け取ることになり、どのサービスが代理で動いているかの記録も失われる。RFC 8693 は認可サーバーを Security Token Service にする。クライアントが subject_token (と任意の actor_token) を提示すると、目的の resource や audience 向けの新しいトークンを受け取り、委任の連鎖はトークン自体に書き込まれる (Section 1, Section 4.1)。

仕組み

図
sequenceDiagram
    participant C as クライアント (サービス A)
    participant AS as 認可サーバー (STS)
    participant RS as Backend B
    C->>AS: POST /token grant_type=token-exchange, subject_token, subject_token_type, resource か audience, scope
    Note over C,AS: delegation なら actor_token と actor_token_type も付ける
    AS->>AS: subject_token と actor_token を検証、may_act とポリシーを確認
    AS-->>C: access_token, issued_token_type, token_type, expires_in, scope
    C->>RS: 発行されたトークンでリクエスト
    RS-->>C: 応答

クライアントは grant_type=urn:ietf:params:oauth:grant-type:token-exchange を送り、手元のトークンを subject_token、その種類を subject_token_type に入れ、宛先を resource (URI) か audience (論理名) で指定する。delegation なら actor_token を添える。認可サーバーはリクエスト中のトークンをすべて検証し、何を発行するか決め、access_token と、返ってきたトークンの種類を示す issued_token_type を返す。delegation トークンなら sub は元の subject のままで、act が現在の actor を示し、以前の actor はその中に入れ子で残る (Section 2.1, Section 2.2.1, Section 4.1)。

仕様が求めること

  • grant_type は urn:ietf:params:oauth:grant-type:token-exchange でなければならない。subject_token と subject_token_type は REQUIRED。actor_token_type は actor_token があるとき REQUIRED で、ないときは含めてはならない (Section 2.1)。
  • 認可サーバーは subject_token と、あれば actor_token を、それぞれの種類に応じて検証しなければならない (Section 2.1)。
  • resource は絶対 URI でフラグメントを含んではならない。audience はその認可サーバー内で一意な論理名。どちらも複数指定でき、併用もできる (Section 2.1)。
  • 応答には access_token、issued_token_type、token_type が必須。発行したトークンが access token でなければ token_type は N_A。scope は要求と異なるときに REQUIRED (Section 2.2.1)。
  • 不正なリクエストや拒否されたトークンには invalid_request を返さなければならない。要求された resource や audience 向けに発行できないときは invalid_target を返すべき (Section 2.2.2)。
  • act claim 付きトークンの消費者は、アクセス制御の判断でトップレベルの claim と現在の actor だけを考慮しなければならない。以前の actor は参考情報 (Section 4.1)。
  • トークン内の may_act claim は、その subject の actor になることを許された当事者を示す (Section 4.4)。

注意点

  • クライアント認証は認可サーバーの裁量。認証なしではトークンを持つ誰もが交換できる。誰が impersonation や delegation を受けられるかを決める手段が認証になる (Section 2.1)。
  • 交換は一回きりの出来事。入力トークンを更新しても出力は延びず、入力の失効も配備側で仕組みを足さない限り伝播しない (Section 2.1)。
  • 宛先を一度にたくさん要求すると拒否されやすい。実効的なアクセスは全宛先にわたる scope の積になるので、要求は絞る (Section 2.1.1)。
  • delegation も impersonation も、ある principal が別の principal の権限を行使できるようにする。scope claim で委任された権限の適用先を限定し、トークンの寿命を短くする (Section 5)。
  • トークンは機微な情報を含みうるので暗号化された経路でしか送ってはならない。クライアントから隠す必要があれば、受け取り手向けに暗号化する (Section 6)。

出典

他の仕様との関係

関係図
flowchart LR
  s_token_exchange["Token Exchange"]
  s_oauth2["OAuth 2.0"]
  s_identity_chaining["Identity and Authorization Chaining"]
  s_id_jag["Identity Assertion JWT Authorization Grant"]
  s_txn_tokens["Transaction Tokens"]
  style s_token_exchange stroke-width:3px
  s_token_exchange -->|拡張対象| s_oauth2
  s_identity_chaining -->|土台とする仕様| s_token_exchange
  s_id_jag -->|土台とする仕様| s_token_exchange
  s_txn_tokens -->|土台とする仕様| s_token_exchange

公式に文書化された対応

利用状況には、公式のドキュメント(ベンダーやプロジェクト自身のもの、または標準化団体がその名前を挙げているページ)に対応が明記されているものだけを載せている。引用した文言がそのページにまだあるかは毎週確認している。実験的・アルファ・ベータの対応は「プレビュー」として別に数える。

製品・IdP・サービス

  • Keycloak (IdP): RFC 8693 を実装した標準のトークン交換 出典 (確認 2026-11-11)
  • Google Cloud (クラウド): Security Token Service が標準の OAuth 2.0 トークン交換を実装 出典 (確認 2026-11-11)
  • Okta (IdP): カスタム認可サーバーでの On-Behalf-Of トークン交換 出典 (確認 2026-11-11)

動き

Datatracker の revision 履歴、このサイトの日次 run が書いた解説、draft 名を挙げた ML の件名。

このサイトの解説

  • evidence-binding の著者らは、停止された先行アクターに関する記述を RFC 8693 第4.1節と矛盾しないよう限定することにした。

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

    解説を読む

    Shameer は Mikhail の二点の指摘を受け入れた。Serving Party が先行アクターの停止を理由に呼び出しを拒否できないという記述は広すぎた。RFC 8693 第4.1節が排除しているのは入れ子の act クレームをその判断に用いることであり、別途検証された委任トークンの利用ではない。文言は「先行アクターがその後停止されたことを、入れ子の act クレームに基づいて理由に呼び出しを拒否することはできない」に改められる。「完全でも証拠でもない」という履歴に関する表現は、「それ自体では完全であること、あるいはいずれかのホップが権限を保持または縮小したことを立証しない」に置き換えられる。どちらの修正も SCITT ドラフトと Evidence Binding ドラフトの次版に反映される。このメッセージ自体にドラフト本文は含まれていない。

    • 入れ子の act クレームではなく検証済み委任トークンを用いて、停止された先行アクターを理由に呼び出しを拒否できるか判断する Serving Party。
    • 関連: OAuth WG: draft-ietf-oauth-transaction-tokens. 弱い関連のみ。いずれもホップ間の委任コンテキストを扱うが、資料に直接の言及はない。
  • Mikhailは、過去のアクターが停止されたことを理由に呼び出しを拒否できないとする記述の修正を、エビデンス束縛ドラフトの著者に求めた。

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

    解説を読む

    KieranはRFC 8693 Section 4.1により、入れ子のactクレーム内の過去のアクターはアクセス制御の判断に使えないという読みを認め、著者は-02でこれを取り入れるとしている。Mikhailは、SCITT -02の本文が依然として、過去のアクターが停止されたことを理由にServing Partyが呼び出しを拒否できないと記している点を指摘した。別途検証された委任トークンは別の根拠となる。draft-asor-wimse-agent-delegation-chain-03形式のチェーンはホップごとに検証され、ステップ7では、受け入れたステータス応答がいずれかのトークンを失効としていれば、ステータスリストの鮮度の範囲内で拒否される。そこで、拒否できないのは入れ子のactクレームに基づく場合に限るという文言と、履歴が完全でも証拠でもないという表現の修正を提案している。

    flowchart LR
    A[Token with nested act claims] --> B[Serving party reads top-level claims and current actor only]
    C[Delegation chain tokens] --> D[Verify each hop]
    D --> E[Check status list answer]
    E -->|any token revoked| F[Deny]
    • 上流のアクターが後から停止される、複数ホップのエージェント呼び出しの監査やServing Partyのポリシーを設計する場合。
    • ホップごとの権限を、act クレーム(帰属のみ)から確認するか、ステータス参照を持つ別途検証された委任トークンから確認するかを選ぶ場合。
    • 関連: OAuth WG: draft-ietf-oauth-status-list. 委任チェーンドラフトのステータス参照と鮮度は、ステータスリストの応答に対して確認される。
  • 新しい提案OAuth WG

    新規の個人ドラフトが Agent Passport と Delegation Receipt を定義し、Token Exchange で発行する

    New draft: Agent Passports and Delegation Receipts (draft-le-agent-passport-00)

    解説を読む

    draft-le-agent-passport-00 は二種類の署名付きオブジェクトを定義する。Agent Passport は、エージェントの鍵(cnf)を責任を負う組織とビルドのダイジェストに結び付ける JWT である。Delegation Receipt はユーザーからエージェント、サブエージェントへ続く連鎖で、各段は鍵に束縛され、前の段より権限を狭めることしかできない。依拠当事者は連鎖を検証し、ユーザー自身のアクセス権との共通部分を取る。ルートの receipt は RFC 8693 の Token Exchange で取得し、passport を actor token とし、新しい requested_token_type urn:ietf:params:oauth:token-type:agent-delegation を用いる。ステータスは Token Status List ドラフトで表す。未解決の論点は、付与を RFC 9396 の authorization_details の type として表すべきかどうかである。著者は IETF 127 でのサイドミーティングと IPR 開示にも触れ、draft-klrc-aiagent-auth や AAuth を補完するものだと述べている。

    sequenceDiagram
      participant U as User
      participant A as Agent
      participant AS as Authorization Server
      participant RP as Relying Party
      A->>AS: Token Exchange, actor_token = Agent Passport
      AS-->>A: root Delegation Receipt (agent-delegation type)
      A->>A: sub-agent receipt, narrower than parent
      A->>RP: passport and receipt chain
      RP->>RP: verify chain, intersect with user access
    • RAR に対応済みの認可サーバーが、エージェントへの委任を authorization_details として発行したい場合
    • 組織をまたいで、サブエージェントの権限がユーザーの権限の部分集合であることを依拠当事者が検証する必要がある場合
    • 関連: OpenID: openid/aauth. 著者は、このドラフトは AAuth を補完するものだと述べている。