第7章 トークンの交換
トークンの交換は テクノロジープレビュー であるため、完全にサポートされていません。この機能はデフォルトでは無効になっています。
-Dkeycloak.profile=preview または -Dkeycloak.profile.feature.token_exchange=enabled でサーバーの起動を有効にするには、以下を行います、詳細は「プロファイル」を参照してください。
トークンの交換を使用するには、admin_fine_grained_authz 機能も有効にする必要があります。プロファイル を確認してください。
Red Hat Single Sign-On では、トークン交換は、一連の認証情報またはトークンを使用して、まったく異なるトークンを取得するプロセスです。クライアントは、信頼性の低いアプリケーションで呼び出したい場合があるため、現在のトークンをダウングレードしたい場合があります。クライアントは、Red Hat Single Sign-On トークンをリンクされたソーシャルプロバイダーアカウント用に保存されているトークンと交換したい場合があります。他の Red Hat Single Sign-On レルムまたは外部 IDP によって作成された外部トークンを信頼することをお勧めします。クライアントでは、ユーザーの権限を借用しなければならない場合があります。以下は、トークン交換に関する Red Hat Single Sign-On の現在の機能の概要です。
- クライアントは、特定のクライアント用に作成された既存の Red Hat Single Sign-On トークンを、別のクライアントを対象とする新しいトークンと交換できます。
- クライアントは、既存の Red Hat Single Sign-On トークンを外部トークン (リンクされた Facebook アカウントなど) と交換できます。
- クライアントは、外部トークンを、Red Hat Single Sign-On トークンと交換できます。
- クライアントはユーザーの権限を借用できます。
Red Hat Single Sign-On でのトークン交換は、IETF での OAuth トークン交換 仕様の実装は非常に緩やかです。この仕様を少し拡張し、一部を無視して、他の部分は大まかに解釈しました。これは、レルムの OpenID Connect トークンエンドポイントにおける単純な付与タイプ呼び出しです。
/auth/realms/{realm}/protocol/openid-connect/token
これは、フォームパラメーター (application/x-www-form-urlencoded) を入力として受け付け、出力は交換を要求したトークンのタイプによって異なります。トークン交換はクライアントエンドポイントであるため、リクエストは呼び出し元のクライアントに対して認証情報を提供する必要があります。パブリッククライアントは、クライアント識別子を form パラメーターとして指定します。機密クライアントは、フォームパラメータを使用して、クライアント ID とシークレット、Basic 認証、または管理者がレルムで設定したクライアント認証フローを渡すこともできます。以下は、フォームパラメーターの一覧です。
- client_id
- 必須の可能性あり。このパラメーターは、認証にフォームパラメーターを使用するクライアントに必要です。Basic 認証、クライアント JWT トークン、またはクライアント証明書認証を使用している場合は、このパラメーターを指定しないでください。
- client_secret
- 必須の可能性あり。このパラメーターは、認証にフォームパラメーターを使用し、認証情報としてクライアントシークレットを使用するクライアントに必要です。レルムのクライアント呼び出しが別の手段で認証されている場合は、このパラメーターは指定しないでください。
- grant_type
-
必須。パラメーターの値は
urn:ietf:params:oauth:grant-type:token-exchangeにする必要があります。 - subject_token
- 任意です。リクエストが行われている当事者の ID を表すセキュリティトークン。これは、既存のトークンを新しいトークンと交換する場合に必要です。
- subject_issuer
-
任意です。
subject_tokenの発行者を特定します。トークンが現在のレルムから送信される場合や、発行者がsubject_token_typeから判断できる場合は空白のままにすることができます。それ以外の場合は指定する必要があります。有効な値は、レルムに設定されたID プロバイダーのエイリアスです。または、特定のID プロバイダーによって設定された発行者要求 ID です。 - subject_token_type
-
任意です。このパラメーターは、
subject_tokenパラメーターで渡されるトークンのタイプです。subject_tokenがレルムから取得され、アクセストークンである場合、デフォルトはurn:ietf:params:oauth:token-type:access_tokenに設定されます。外部トークンの場合には、subject_issuerの要件に応じてこのパラメーターを指定する必要がある場合とそうでない場合があります。 - requested_token_type
-
任意です。このパラメーターは、クライアントが交換するトークンのタイプを表します。現在、oauth および OpenID Connect トークンタイプのみがサポートされます。このデフォルト値が
urn:ietf:params:oauth:token-type:refresh_tokenであるかどうかによって異なります。この場合、応答内でアクセストークンと更新トークンの両方が返されます。その他の適切な値は、urn:ietf:params:oauth:token-type:access_tokenおよびurn:ietf:params:oauth:token-type:id_tokenです。 - audience
- 任意です。このパラメーターは、新しいトークンを作成するターゲットクライアントを指定します。
- requested_issuer
-
任意です。このパラメーターは、クライアントが外部プロバイダーによって作成されたトークンを必要とすることを指定します。レルム内で設定された
ID プロバイダーのエイリアスである必要があります。 - requested_subject
- 任意です。これは、クライアントが別のユーザーになりすます場合のユーザー名またはユーザー ID を指定します。
- scope
- 実装ない。このパラメーターは、クライアントが要求する OAuth および OpenID Connect スコープのターゲットセットを表します。現時点では実装されていませんが、Red Hat Single Sign-On がスコープ全般をより適切にサポートするようになると実装されます。
現在、OpenID Connect および OAuth の交換のみをサポートします。SAML ベースのクライアントおよびアイデンティティープロバイダーのサポートは、ユーザーの需要に応じて今後追加される可能性があります。
交換呼び出しからの正常な応答は、クライアントが要求する requested-token-type と requested_issuer に依存するコンテンツタイプを含む HTTP 200 応答コードを返します。OAuth が要求するトークンタイプは、OAuth Token Exchange 仕様説明されているように JSON ドキュメントを返します。
{
"access_token" : ".....",
"refresh_token" : ".....",
"expires_in" : "...."
}
更新トークンを要求するクライアントは、応答でアクセストークンと更新トークンの両方を返します。アクセストークンタイプのみを要求するクライアントは、応答でアクセストークンのみを取得します。requested_issuer パラメーターを介して外部発行者を要求するクライアントの有効期限情報は、含まれる場合とそうでない場合があります。
通常、エラー応答は 400 HTTP 応答コードカテゴリーに分類されますが、エラーの重大度に応じて他のエラーステータスコードが返される場合があります。エラー応答には、requested_issuer に依存するコンテンツが含まれる場合があります。OAuth ベースの交換では、以下のように JSON ドキュメントが返される場合があります。
{
"error" : "...."
"error_description" : "...."
}
交換タイプに応じて、追加のエラークレームを返すことができます。たとえば、ユーザーに ID プロバイダーへのリンクがない場合に、OAuth ID プロバイダーには追加の account-link-url 要求が含まれる場合があります。このリンクは、クライアントが開始したリンク要求に使用できます。
トークンの交換の設定には、きめ細かな管理パーミッションに関する知識が必要です (詳細は、『サーバー管理ガイド』を参照)。交換にクライアントパーミッションを付与する必要があります。これについては、この章で後ほど説明します。
この章の残りの部分では、セットアップ要件について説明し、さまざまな交換シナリオの例を示します。分かりやすくするために、現在のレルムで作成された最小のトークンを 内部 トークンとして呼び出し、外部レルムまたは ID プロバイダーによって作成されたトークンを 外部 トークンと呼ぶことにします。
7.1. 内部トークンから内部トークンへの交換
内部のトークンからトークンへの交換では、特定のクライアントに作成された既存のトークンがあり、このトークンを別のターゲットクライアントに作成された新しいトークンと交換する必要があります。これを実行する理由これは通常、クライアントが自身のために作成したトークンを持っており、アクセストークン内で異なるクレームとパーミッションを必要とする他のアプリケーションに追加の要求を行う必要がある場合に発生します。このタイプの交換が必要となるかもしれないその他の理由は、アプリが信頼性の低いアプリで呼び出す必要があり、現在のアクセストークンを伝播したくない場合の「パーミッションのダウングレード」を実行する必要がある場合です。
7.1.1. Exchange のパーミッションの付与
別のクライアントのトークンを交換する必要のあるクライアントは、管理コンソールで承認される必要があります。交換するパーミッションを付与するクライアントに、token-exchange の細かいパーミッションを定義する必要があります。
ターゲットクライアントパーミッション
Permissions Enabled スイッチを ON に切り替えます。
ターゲットクライアントパーミッション
ページに token-exchange リンクが表示されます。それをクリックして、パーミッションの定義を開始します。このページが作成されます。
ターゲットクライアント交換のパーミッション設定
このパーミッションのポリシーを定義する必要があります。Authorization リンクをクリックし、Policies タブに移動し、Client ポリシーを作成します。
クライアントポリシーの作成
ここでは、トークン交換を要求する認証されたクライアントである、開始クライアントを入力します。このポリシーを作成したら、ターゲットクライアントの token-exchange パーミッションに戻り、定義したクライアントポリシーを追加します。
クライアントポリシーの適用
これでクライアントを呼び出すパーミッションがある。これを正しく行わないと、エクスチェンジを作成しようとすると、403 Forbidden 応答が返されます。
7.1.2. リクエストの作成
クライアントが、既存のトークンを他のクライアントをターゲットにしたトークンと交換する場合は、audience パラメーターを使用する必要があります。このパラメーターは、管理コンソールで設定したターゲットクライアントのクライアント識別子である必要があります。
curl -X POST \
-d "client_id=starting-client" \
-d "client_secret=geheim" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=...." \
--data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:refresh_token" \
-d "audience=target-client" \
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
subject_token パラメーターは、ターゲットレルムのアクセストークンである必要があります。requested_token_type パラメーターが更新トークンタイプである場合、応答にはアクセストークン、更新トークン、および有効期限が含まれます。以下は、この呼び出しから返される JSON 応答の例です。
{
"access_token" : "....",
"refresh_token" : "....",
"expires_in" : 3600
}