> ## Documentation Index
> Fetch the complete documentation index at: https://developers.authlete.com/llms.txt
> Use this file to discover all available pages before exploring further.

# RFC 8693 OAuth 2.0 Token Exchange

> RFC 8693 OAuth 2.0 Token Exchange 仕様と Authlete の実装の説明です。

<Note>
  このページは Authlete 3.0 用です。2.x については[こちらのページ](/ja/v2/protocols-and-flows/grant-types/token-exchange)をご覧ください。
</Note>

# はじめに

[RFC 8693 OAuth 2.0 Token Exchange](https://www.rfc-editor.org/rfc/rfc8693.html) (以下 "Token Exchange") は、トークンエンドポイントに既存のトークンを提示して新しいトークンを取得する方法を定義している技術仕様です。

当仕様はとても柔軟ですが、実のところ、安全なトークン交換に必要となる詳細事項については定義されていません。そのため、同仕様を認可サーバーに実装する際には、未定義部分に関する詳細仕様化が必要です。

本記事では、Token Exchange 仕様を用いる場合の詳細仕様化の要点と、Authlete における同仕様のサポートについて説明します。

# 仕様

次の図はトークン交換フローを示しています。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/advanced-flows/token_exchange_ja.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=1290a0c11ff8c5f58a38771bc0c3a2c5" alt="" width="3153" height="1805" data-path="protocols-and-flows/advanced-flows/token_exchange_ja.png" />

以下のセクションでは、トークンのタイプ、そしてトークン交換リクエスト・レスポンスについて述べます。

## トークンの種別

トークン交換フローにおいて入力として提示するトークンには、サブジェクトトークン (Subject Token) とアクタートークン (Actor Token) の 2 種類があります。

### サブジェクトトークン

サブジェクトトークンは提示が必須のトークンです。RFC 8693 では以下のように定義されています。

> ( [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) [Section 2.1. Request](https://www.rfc-editor.org/rfc/rfc8693.html#section-2.1) より抜粋 )

> A subject token represents the identity of the party on behalf of whom the request is being made.
>
> サブジェクトトークンは、リクエストの当事者のアイデンティティを表すものである。

つまり、サブジェクトトークンにより特定されるサブジェクトが、新しく発行されるトークンのサブジェクトとして用いられることが想定されています。

### アクタートークン

アクタートークンは任意に提示するトークンです。RFC 8693 では以下のように定義されています。

> ( [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) [Section 2.1. Request](https://www.rfc-editor.org/rfc/rfc8693.html#section-2.1) より抜粋 )

> An actor token represents the identity of the acting party.
>
> アクタートークンは、代行者のアイデンティティを表すものである。

新しく発行されたトークンのサブジェクトと、そのトークンを利用する代行者とを区別する必要がある場合、認可サーバーはアクタートークンを活用し、発行するトークンに代行者に関する情報を埋め込んでもよいでしょう。[RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) の [4.1 節](https://www.rfc-editor.org/rfc/rfc8693.html#section-4.1)と [4.4 節](https://www.rfc-editor.org/rfc/rfc8693.html#section-4.4)は、代行者に関連する JWT クレームを定義しています。

### トークンタイプ

これらのトークンが取りうる型として、仕様は次の**トークンタイプ**を列挙し、それぞれにトークンタイプ識別子を割り当てています。これらのトークンタイプ識別子は IANA (Internet Assigned Numbers Authority) の [OAuth Parameters](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml) / [OAuth URI](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#uri) に登録されています。

| トークンタイプ         | トークンタイプ識別子                                       |
| :-------------- | :----------------------------------------------- |
| JWT             | `urn:ietf:params:oauth:token-type:jwt`           |
| アクセストークン        | `urn:ietf:params:oauth:token-type:access_token`  |
| リフレッシュトークン      | `urn:ietf:params:oauth:token-type:refresh_token` |
| ID トークン         | `urn:ietf:params:oauth:token-type:id_token`      |
| SAML 1.1 アサーション | `urn:ietf:params:oauth:token-type:saml1`         |
| SAML 2.0 アサーション | `urn:ietf:params:oauth:token-type:saml2`         |

<Note>
  JWT 用のトークンタイプ識別子は [RFC 7519 JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519.html) で定義されています。他の識別子は [RFC 8693 OAuth 2.0 Token Exchange](https://www.rfc-editor.org/rfc/rfc8693.html) で定義されています。
</Note>

## トークン交換リクエスト

**トークン交換リクエスト**はトークンリクエストの一種です。

### グラントタイプ

他のトークンリクエストとトークン交換リクエストを区別するため、新しいグラントタイプ `urn:ietf:params:oauth:grant-type:token-exchange` が仕様で定義されています。この値はトークンリクエストの `grant_type` リクエストパラメーターの値として使用されます。

### クライアントの特定と認証

仕様自体は、トークンエンドポイントにおける[クライアント認証](https://qiita.com/TakahikoKawasaki/items/63ed4a9d8d6e5109e401)やクライアントの特定を要求していません。これについて [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) の [Section 2.1. Request](https://www.rfc-editor.org/rfc/rfc8693.html#section-2.1) は次のように述べています。

> The supported methods of client authentication and whether or not to allow **unauthenticated** or **unidentified** clients are deployment decisions that are at the discretion of the authorization server.
>
> サポートするクライアント認証方式や、**未認証**または**未特定**のクライアントを許容するかどうかは、認可サーバーの自由裁量の範疇で運用方針に応じて決定する事項である。

技術的には、『未認証のクライアント』はパブリッククライアントを意味し (参照: [RFC 6749](https://www.rfc-editor.org/rfc/rfc6749.html) [Section 2.1. Client Types](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1))、『未特定のクライアント』はトークンリクエストがクライアントを特定するための情報を含んでいないことを意味します。

[RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) の[付録 1.1](https://www.rfc-editor.org/rfc/rfc8693.html#section-a.1.1) には特定不能なクライアントからのトークン交換リクエストの例が示されていますが、このようなケースは、サービス内の閉じた環境のような、特定の条件下に限られます。それ以外の場合には、安全なトークン交換のための詳細仕様化を行い、[RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) を補完する必要があります。

### リクエストパラメーター

トークン交換リクエストに関連するパラメーターを以下に示します。

| リクエストパラメーター            |  要否 | 説明                                                                                                                                                                |
| :--------------------- | :-: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `grant_type`           |  必須 | `urn:ietf:params:oauth:grant-type:token-exchange` という値によりトークンリクエストがトークン交換リクエストであることが示されます。                                                                        |
| `resource`             |  任意 | 新しく発行されるトークンに結び付けられるリソース。このリクエストパラメーターは複数回指定してもよいとされています。詳細は [RFC 8707 Resource Indicators for OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8707.html) を参照してください。 |
| `audience`             |  任意 | 新しく発行されるトークンの対象。このリクエストパラメーターも複数回指定してもよいとされています。                                                                                                                  |
| `scope`                |  任意 | 新しく発行されるトークンに結び付けられるスコープ群の名前をスペース区切りで並べたもの。                                                                                                                       |
| `requested_token_type` |  任意 | クライアントが希望する、新しく発行されるトークンのトークンタイプ。登録されているトークンタイプ識別子のいずれか。                                                                                                          |
| `subject_token`        |  必須 | サブジェクトトークンの値。                                                                                                                                                     |
| `subject_token_type`   |  必須 | サブジェクトトークンのトークンタイプ。登録されているトークンタイプ識別子のいずれか。                                                                                                                        |
| `actor_token`          |  任意 | アクタートークンの値。                                                                                                                                                       |
| `actor_token_type`     |  任意 | アクタートークンのトークンタイプ。登録されているトークンタイプ識別子のいずれか。`actor_token` リクエストパラメーターが与えられている場合、このリクエストパラメーターは必須。逆に、`actor_token` リクエストパラメーターが与えられていない場合、このリクエストパラメーターが存在していてはいけません。  |

<Note>
  [RFC 6749 The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html) は "Request and response parameters MUST NOT be included more than once." (リクエストパラメーターとレスポンスパラメーターは複数回含まれていてはならない) と述べています。`resource` リクエストパラメーターと `audience` リクエストパラメーターは例外です。
</Note>

## トークン交換レスポンス

**トークン交換レスポンス**はトークンレスポンスの一種です。

### レスポンスパラメーター

トークン交換レスポンスに関連するパラメーターを以下に示します。

| レスポンスパラメーター         |  要否 | 説明                                                                                                                                                                                                                                     |
| :------------------ | :-: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `access_token`      |  必須 | トークンタイプに関わらず、新しく発行されたトークンの値はこのレスポンスパラメーターにセットされます。                                                                                                                                                                                     |
| `issued_token_type` |  必須 | 新しく発行されたトークンのトークンタイプ。登録されているトークンタイプ識別子のいずれか。                                                                                                                                                                                           |
| `token_type`        |  必須 | 新しく発行されたトークンのトークンタイプが `urn:ietf:params:oauth:token-type:access_token` のとき、このレスポンスパラメーターは [RFC 6749 The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html) で定義されているものと同じ意味を持ちます。それ以外の場合は `"N_A"` がセットされます。 |
| `expires_in`        |  任意 | 新しく発行されたトークンの有効時間 (秒単位)。                                                                                                                                                                                                               |
| `scope`             |  任意 | 新しく発行されたトークンに結び付けられたスコープ群。新しく発行されたトークンに結び付けられたスコープ群の実際の組がトークン交換リクエストで要求された組と異なる場合、このレスポンスパラメーターは必須。                                                                                                                                    |
| `refresh_token`     |  任意 | リフレッシュトークン (参照: [RFC 6749](https://www.rfc-editor.org/rfc/rfc6749.html) [Section 6. Refreshing an Access Token](https://www.rfc-editor.org/rfc/rfc6749.html#section-6))。                                                               |

# Authlete における対応

本セクションでは、Authlete の Token Exchange 対応について解説します。なお同仕様は Authlete 2.3 以降でサポートされます。

## トークン交換リクエスト

### /auth/token API のアクション値

クライアントからトークンリクエストを受信した認可サーバーは、そのリクエストの内容を Authlete の [`/auth/token`](https://docs.authlete.com/en/shared/latest#post-/api/auth/token) API に引数として送信します。同 API は与えられたトークンリクエストに関し、

* `grant_type` パラメーターの値が `urn:ietf:params:oauth:grant-type:token-exchange` であり、かつ
* そのリクエストが Authlete サーバー側で実行される基本的なバリデーション処理をパスした

場合に、`action` パラメーターの値として `TOKEN_EXCHANGE` を含むレスポンスを返却します。

その他、`/auth/token` API からのレスポンスに含まれるトークン交換関連のパラメーターを、次の表に示します。

| レスポンスパラメーター          | 型      | 説明                                                                                                                                                                                |
| :------------------- | :----- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `resources`          | 文字列配列  | `resource` リクエストパラメーター群の値。                                                                                                                                                        |
| `audiences`          | 文字列配列  | `audience` リクエストパラメーター群の値。                                                                                                                                                        |
| `scopes`             | 文字列配列  | `scope` リクエストパラメーターに列挙されたスコープ群。                                                                                                                                                   |
| `requestedTokenType` | 文字列    | `requested_token_type` リクエストパラメーターの値を示す文字列。 `"ACCESS_TOKEN"` など。(参照:  [TokenType.java](https://authlete.github.io/authlete-java-common/com/authlete/common/types/TokenType.html)) |
| `subjectToken`       | 文字列    | `subject_token` リクエストパラメーターの値。                                                                                                                                                    |
| `subjectTokenType`   | 文字列    | `subject_token_type` リクエストパラメーターの値を示す文字列。 `"ACCESS_TOKEN"` など。(参照:  [TokenType.java](https://authlete.github.io/authlete-java-common/com/authlete/common/types/TokenType.html))   |
| `subjectTokenInfo`   | オブジェクト | サブジェクトトークンに関する情報。トークンタイプがアクセストークンかリフレッシュトークンの場合のみ利用可能。                                                                                                                            |
| `actorToken`         | 文字列    | `actor_token` リクエストパラメーターの値。                                                                                                                                                      |
| `actorTokenType`     | 文字列    | `actor_token_type` リクエストパラメーターの値を示す文字列。 `"ACCESS_TOKEN"` など。(参照:  [TokenType.java](https://authlete.github.io/authlete-java-common/com/authlete/common/types/TokenType.html))     |
| `actorTokenInfo`     | オブジェクト | アクタートークンに関する情報。トークンタイプがアクセストークンかリフレッシュトークンの場合のみ利用可能。                                                                                                                              |

## トークンのバリデーション

入力トークンのバリデーションについて、RFC 8693 には次のように記述されています。

> In processing the request, the authorization server MUST perform the appropriate validation procedures for the indicated token type and, if the actor token is present, also perform the appropriate validation procedures for its indicated token type. The validity criteria and details of any particular token are beyond the scope of this document and are specific to the respective type of token and its content.

つまり、適切なバリデーションが必須である (MUST) とされていますが、その基準や手順については RFC 8693 では定められておらず、この仕様を実装する認可サーバーに委ねられています。そのようなバリデーション実装の負担を軽減するため、Authlete の `/auth/token` API は次の処理を行います。

|  番号 | バリデーション                                                                                                   |
| :-: | :-------------------------------------------------------------------------------------------------------- |
|  1  | `requested_token_type` リクエストパラメーターが与えられていて、その値が空でない場合、その値が登録されているトークンタイプ識別子のいずれかであることを確認する。               |
|  2  | `subject_token` リクエストパラメーターが与えられていること、その値が空でないことを確認する。                                                    |
|  3  | `subject_token_type` リクエストパラメーターが与えらていること、その値が登録されているトークンタイプ識別子のいずれかであることを確認する。                           |
|  4  | `actor_token_type` リクエストパラメーターが与えられていて、その値が空でない場合、その値が登録されているトークンタイプ識別子のいずれかであることを確認する。                   |
|  5  | `actor_token` リクエストパラメーターが与えられていないか、その値が空の場合、`actor_token_type` リクエストパラメーターが与えられていない、もしくはその値が空であることを確認する。 |

Authlete はさらに、トークン交換リクエストに含まれる、`subject_token` リクエストパラメーターと `actor_token` リクエストパラメーターで指定されたトークンに関してバリデーションを行います。その際にどのような処理を行うかは、トークンタイプによって異なります。各トークンタイプにおける処理内容を以下に示します。

### トークンタイプ: JWT

|  番号 | バリデーション                                                                                                                                    |
| :-: | :----------------------------------------------------------------------------------------------------------------------------------------- |
|  1  | フォーマットが JWT 仕様 ([RFC 7519 JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519.html)) に従っていることを確認する。                               |
|  2  | 当 JWT が暗号化されている場合、(a) サービスの `tokenExchangeEncryptedJwtRejected` フラグが `true` であればトークン交換リクエストを拒否し、(b) 当フラグが `false` であれば以降のバリデーション処理をスキップする。 |
|  3  | 当 JWT が `exp` クレームを含んでいる場合、現在時刻が当クレームで示される時刻に達していないことを確認する。                                                                                |
|  4  | 当 JWT が `iat` クレームを含んでいる場合、現在時刻が当クレームで示される時刻以降であることを確認する。                                                                                  |
|  5  | 当 JWT が `nbf` クレームを含んでいる場合、現在時刻が当クレームで示される時刻以降であることを確認する。                                                                                  |
|  6  | 当 JWT が無署名の場合、(a) サービスの `tokenExchangeUnsignedJwtRejected` フラグが `true` であればトークン交換リクエストを拒否し、(b) 当フラグが `false` であれば入力トークンに対するバリデーション処理を終了する。 |
|  7  | (当 JWT の署名は検証されない。)                                                                                                                        |

<Note>
  JWT の復号化に使う鍵を取得する標準的な方法が存在しないため、Authlete は暗号化された JWT のバリデーションをおこないません。これは、暗号化された JWT がトークンタイプ `urn:ietf:params:oauth:token-type:jwt` の入力トークンとして用いられた場合、(サービスの `tokenExchangeEncryptedJwtRejected` フラグが `false` の場合) **あなた自身で暗号化された JWT のバリデーションを実施しなければならない**ということを意味します。
</Note>

<Note>
  JWT の署名検証に使う鍵を取得する標準的な方法が存在しないため、Authlete は JWT の署名を検証しません。これは、署名された JWT がトークンタイプ `urn:ietf:params:oauth:token-type:jwt` の入力トークンとして用いられた場合、**あなた自身で JWT の署名を検証しなければならない**ということを意味します。
</Note>

### トークンタイプ: アクセストークン

|  番号 | バリデーション                                                  |
| :-: | :------------------------------------------------------- |
|  1  | トークンが、あなたのサービスの Authlete サーバーにより発行されたアクセストークンであることを確認する。 |
|  2  | 当アクセストークンが有効期限切れしていないことを確認する。                            |
|  3  | 当アクセストークンが当サービスに属していることを確認する。                            |

<Note>
  上述のバリデーション処理は、他のシステムが発行したアクセストークンを、トークンタイプ `urn:ietf:params:oauth:token-type:access_token` のサブジェクトトークンやアクタートークンとして用いることができないことを示唆しています。当バリデーション処理を無効化するためのオプションを Authlete は将来提供するかもしれませんが、本記事執筆時点ではその計画はありません。
</Note>

### トークンタイプ: リフレッシュトークン

|  番号 | バリデーション                                                    |
| :-: | :--------------------------------------------------------- |
|  1  | トークンが、あなたのサービスの Authlete サーバーにより発行されたリフレッシュトークンであることを確認する。 |
|  2  | 当リフレッシュトークンが有効期限切れしていないことを確認する。                            |
|  3  | 当リフレッシュトークンが当サービスに属していることを確認する。                            |

<Note>
  上述のバリデーション処理は、他のシステムが発行したリフレッシュトークンを、トークンタイプ `urn:ietf:params:oauth:token-type:refresh_token` のサブジェクトトークンやアクタートークンとして用いることができないことを示唆しています。当バリデーション処理を無効化するためのオプションを Authlete は将来提供するかもしれませんが、本記事執筆時点ではその計画はありません。
</Note>

### トークンタイプ: ID トークン

|  番号 | バリデーション                                                                                                                                       |
| :-: | :-------------------------------------------------------------------------------------------------------------------------------------------- |
|  1  | フォーマットが JWT 仕様 ([RFC 7519 JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519.html)) に従っていることを確認する。                                  |
|  2  | 当 ID トークンが暗号化されている場合、(a) サービスの `tokenExchangeEncryptedJwtRejected` フラグが `true` であればトークン交換リクエストを拒否し、(b) 当フラグが `false` であれば以降のバリデーション処理をスキップする。 |
|  3  | 当 ID トークンが `exp` クレームを含んでおり、現在時刻が当クレームで示される時刻に達していないことを確認する。                                                                                  |
|  4  | 当 ID トークンが `iat` クレームを含んでおり、現在時刻が当クレームで示される時刻以降であることを確認する。                                                                                    |
|  5  | 当 ID トークンが `nbf` クレームを含んでいる場合、現在時刻が当クレームで示される時刻以降であることを確認する。                                                                                  |
|  6  | 当 ID トークンが `iss` クレームを含んでおり、その値が有効な URI であることを確認する。加えて、当 URI が `https` スキームを持つこと、クエリー部を持たないこと、フラグメント部を持たないことを確認する。                            |
|  7  | 当 ID トークンが `aud` クレームを含んでおり、その値が JSON 文字列もしくは JSON 文字列の配列であることを確認する。                                                                          |
|  8  | 当 ID トークンが `nonce` クレームを含んでいる場合、その値が JSON 文字列であることを確認する。                                                                                      |
|  9  | 当 ID トークンが無署名の場合、(a) サービスの `tokenExchangeUnsignedJwtRejected` フラグが `true` であればトークン交換リクエストを拒否し、(b) 当フラグが `false` であれば入力トークンに対するバリデーション処理を終了する。 |
|  10 | 当 ID トークンの署名アルゴリズムが非対称鍵系であることを確認する。                                                                                                           |
|  11 | 当 ID トークンの署名を検証する。                                                                                                                            |

<Note>
  暗号化された ID トークン用のクライアント ID を決定することができないトークン交換の文脈においては、ID トークンの復号化に使う鍵を取得する標準的な方法が存在しないため、Authlete は暗号化された ID トークンのバリデーションをおこないません。これは、暗号化された ID トークンがトークンタイプ `urn:ietf:params:oauth:token-type:id_token` の入力トークンとして用いられた場合、(サービスの `tokenExchangeEncryptedJwtRejected` フラグが `false` の場合) **あなた自身で暗号化された ID トークンのバリデーションを実施しなければならない**ということを意味します。
</Note>

<Note>
  上述の 10 番目のバリデーション処理は、署名アルゴリズムが対称鍵系 (`HS256`、`HS384` または `HS512`) の ID トークンをトークンタイプ `urn:ietf:params:oauth:token-type:id_token` のサブジェクトトークンやアクタートークンとして用いることができないことを示唆しています。トークン交換の文脈においては、署名検証に使う対称鍵 (つまりクライアントシークレット) を決定できないからです。
</Note>

<Note>
  ID トークンの発行者があなたのサービスではない場合でも署名検証は実行されます。ただしその場合、発行者は [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html) で定義されているディスカバリーエンドポイントをサポートしなければなりません。サポートしていない場合、署名検証は失敗します。
</Note>

### トークンタイプ: SAML 1.1 アサーション

|  番号 | バリデーション                                 |
| :-: | :-------------------------------------- |
|  1  | (Authlete はこのトークンタイプに対するバリデーションを行いません。) |

### トークンタイプ: SAML 2.0 アサーション

|  番号 | バリデーション                                 |
| :-: | :-------------------------------------- |
|  1  | (Authlete はこのトークンタイプに対するバリデーションを行いません。) |

## トークン交換レスポンス

### /auth/token/create API

認可サーバーは、`/auth/token` API からのレスポンスに基づいて必要なバリデーションを行い、どのようなトークンを発行するかを決定した後に、トークン交換レスポンスをクライアントに返却します。

トークン交換レスポンスの生成には Authlete の [`/auth/token/create`](https://docs.authlete.com/en/shared/latest#post-/api/auth/token/create) API を用います。その際、この API のリクエストパラメーターのうち、`grantType` の値に `TOKEN_EXCHANGE` を指定します。

## 関連する設定項目

既に述べたように、安全なトークン交換のためには、詳細仕様化を行い [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) を補完しなければなりません。その実装を容易にするため、Authlete は次に示す設定項目を提供します。Authlete を用いて認可サーバーを構築する際にご活用ください。

### サービス設定

| 設定項目              |  型  | 説明                                                                                                                                                                                                                                |
| :---------------- | :-: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 特定可能なクライアントのみ     | 真偽値 | 特定不能クライアントによるトークン交換リクエストを拒否するか否か - `Service.tokenExchangeByIdentifiableClientsOnly` ([JavaDoc](https://authlete.github.io/authlete-java-common/com/authlete/common/dto/Service.html#isTokenExchangeByIdentifiableClientsOnly--))  |
| コンフィデンシャルクライアントのみ | 真偽値 | パブリッククライアントによるトークン交換リクエストを拒否するか否か - `Service.tokenExchangeByConfidentialClientsOnly` ([JavaDoc](https://authlete.github.io/authlete-java-common/com/authlete/common/dto/Service.html#isTokenExchangeByConfidentialClientsOnly--)) |
| 許可されたクライアントのみ     | 真偽値 | 明示的な許可を持たないクライアントによるトークン交換リクエストを拒否するか否か - `Service.tokenExchangeByPermittedClientsOnly` ([JavaDoc](https://authlete.github.io/authlete-java-common/com/authlete/common/dto/Service.html#isTokenExchangeByPermittedClientsOnly--)) |
| 暗号化された JWT を拒否    | 真偽値 | 暗号化された JWT を入力トークンとして使うトークン交換リクエストを拒否するか否か - `Service.tokenExchangeEncryptedJwtRejected` ([JavaDoc](https://authlete.github.io/authlete-java-common/com/authlete/common/dto/Service.html#isTokenExchangeEncryptedJwtRejected--))  |
| 無署名の JWT を拒否      | 真偽値 | 無署名の JWT を入力トークンとして使うトークン交換リクエストを拒否するか否か - `Service.tokenExchangeUnsignedJwtRejected` ([JavaDoc](https://authlete.github.io/authlete-java-common/com/authlete/common/dto/Service.html#isTokenExchangeUnsignedJwtRejected--))      |

### クライアント拡張設定

| 設定項目         |  型  | 説明                                                                                                                                                                                                 |
| :----------- | :-: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| トークン交換の明示的許可 | 真偽値 | トークン交換の明示的許可を持つか否か - `ClientExtension.tokenExchangePermitted` ([JavaDoc](https://authlete.github.io/authlete-java-common/com/authlete/common/dto/ClientExtension.html#isTokenExchangePermitted--)) |

# 利用例

## 認可サーバー実装の例

### TOKEN\_EXCHANGE アクションの処理

Authlete を用いた認可サーバー実装がトークン交換をサポートするためには、 `TOKEN_EXCHANGE` アクションを処理しなければなりません。次に示す `switch` 文は [authlete-java-jaxrs](https://github.com/authlete/authlete-java-jaxrs/) ライブラリの [TokenRequestHandler.java](https://github.com/authlete/authlete-java-jaxrs/blob/master/src/main/java/com/authlete/jaxrs/TokenRequestHandler.java) から抜粋したもので、`TOKEN_EXCHANGE` アクション処理の一つの例です。当 `switch` 文には `TOKEN_EXCHANGE` 用の `case` エントリーがあります。

```java theme={null}
// Dispatch according to the action.
switch (action)
{
    case INVALID_CLIENT:
        // 401 Unauthorized
        return ResponseUtil.unauthorized(content, CHALLENGE);

    case INTERNAL_SERVER_ERROR:
        // 500 Internal Server Error
        return ResponseUtil.internalServerError(content);

    case BAD_REQUEST:
        // 400 Bad Request
        return ResponseUtil.badRequest(content);

    case PASSWORD:
        // Process the token request whose flow is "Resource Owner Password Credentials".
        return handlePassword(response);

    case OK:
        // 200 OK
        return ResponseUtil.ok(content);

    case TOKEN_EXCHANGE:
        // Process the token exchange request (RFC 8693)
        return handleTokenExchange(response);

    case JWT_BEARER:
        // Process the token request which uses the grant type
        // urn:ietf:params:oauth:grant-type:jwt-bearer (RFC 7523).
        return handleJwtBearer(response);

    default:
        // This never happens.
        throw getApiCaller().unknownAction("/api/auth/token", action);
}
```

### トークン交換リクエスト処理

Java で書かれたオープンソースの認可サーバー実装サンプルである [java-oauth-server](https://github.com/authlete/java-oauth-server) の [TokenExchanger.java](https://github.com/authlete/java-oauth-server/blob/master/src/main/java/com/authlete/jaxrs/server/api/TokenExchanger.java) が、トークン交換リクエスト処理の実装サンプルとなっています。
なお当実装は一例に過ぎず、商用利用可能な完璧さは意図していないことにご注意ください。

## リクエストとレスポンスの例

以下はトークン交換リクエスト・レスポンスの例です。

### 1. 何らかの方法で ID トークンを用意する。

```shell theme={null}
$ ID_TOKEN=eyJraWQiOiJhdXRobGV0ZS1mYXBpZGV2LWFwaS0yMDE4MDUyNCIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJodHRwczovL2ZhcGlkZXYtYXMuYXV0aGxldGUubmV0LyIsInN1YiI6IjEwMDQiLCJhdWQiOlsiNTg5OTQ2MzYxNDQ0ODA2MyJdLCJleHAiOjE2NTg2NzExMzAsImlhdCI6MTY1ODY3MDgzMCwiYXV0aF90aW1lIjoxNjU4NjcwODMwLCJub25jZSI6IjEyMzQ1Njc4OSIsInZlcmlmaWVkX2NsYWltcyI6eyJ2ZXJpZmljYXRpb24iOnsidHJ1c3RfZnJhbWV3b3JrIjoibmlzdF84MDBfNjNBIn0sImNsYWltcyI6eyJnaXZlbl9uYW1lIjoiSW5nYSIsImZhbWlseV9uYW1lIjoiU2lsdmVyc3RvbmUiLCJiaXJ0aGRhdGUiOiIxOTkxLTExLTA2IiwiOmFnZV8xOF9vcl9vdmVyIjpudWxsfX19.mxE8FQaDb0edY_rWasSQ7pEMXbFon7oWr-Ccv1dB15q8eh2MaKRGrgvwPw_XjAdXlMNzkcV6iEUjRUvLGTvzm7_45cdoOxRX1xWzQw-vwvRbM46xd3Yht3EVjyRUUBJ_92J1yBmu7Nn93rygcnCE-fC_bSTSIJWgEnoC7dpxHYnoJ2QHrIOYFMBAA_3ZYCLGpgiWbIZnB2D1ib2eqwJ9zoJqeFNEBhXo9ThYkASHYaG-ZWofy7364lgeV4Rqy1r4XqzchFRW4yzWs_IM72bTtXTUkstlNOxZU12KEz50uVhtcOXv06iI71I9vceRP-ZVICpq7Knt0vEKWTM41E3ziw
```

### 2. トークン交換リクエストを行う。

```shell theme={null}
$ curl http://localhost:8080/api/token -d grant_type=urn:ietf:params:oauth:grant-type:token-exchange -d subject_token=$ID_TOKEN -d subject_token_type=urn:ietf:params:oauth:token-type:id_token -d client_id=5908895171 -d scope=email
```

### 3. トークン交換レスポンスを受け取る。

```json theme={null}
{
  "access_token":"NEdL-q9EfOI4S5XzaMeimXAXVqS139Jm9DTYeLUAd5o",
  "issued_token_type":"urn:ietf:params:oauth:token-type:access_token",
  "token_type":"Bearer",
  "expires_in":86400,
  "scope":"email",
  "refresh_token":"pK9f5OWIrx58_XWrE_SpCLLN-BM673ljliTSffjqwao"
}
```
