Skip to main content
このページは Authlete 3.0 用です。2.x についてはこちらのページをご覧ください。

はじめに

RFC 8693 OAuth 2.0 Token Exchange (以下 “Token Exchange”) は、トークンエンドポイントに既存のトークンを提示して新しいトークンを取得する方法を定義している技術仕様です。 当仕様はとても柔軟ですが、実のところ、安全なトークン交換に必要となる詳細事項については定義されていません。そのため、同仕様を認可サーバーに実装する際には、未定義部分に関する詳細仕様化が必要です。 本記事では、Token Exchange 仕様を用いる場合の詳細仕様化の要点と、Authlete における同仕様のサポートについて説明します。

仕様

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

トークンの種別

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

サブジェクトトークン

サブジェクトトークンは提示が必須のトークンです。RFC 8693 では以下のように定義されています。
( RFC 8693 Section 2.1. Request より抜粋 )
A subject token represents the identity of the party on behalf of whom the request is being made. サブジェクトトークンは、リクエストの当事者のアイデンティティを表すものである。
つまり、サブジェクトトークンにより特定されるサブジェクトが、新しく発行されるトークンのサブジェクトとして用いられることが想定されています。

アクタートークン

アクタートークンは任意に提示するトークンです。RFC 8693 では以下のように定義されています。
( RFC 8693 Section 2.1. Request より抜粋 )
An actor token represents the identity of the acting party. アクタートークンは、代行者のアイデンティティを表すものである。
新しく発行されたトークンのサブジェクトと、そのトークンを利用する代行者とを区別する必要がある場合、認可サーバーはアクタートークンを活用し、発行するトークンに代行者に関する情報を埋め込んでもよいでしょう。RFC 86934.1 節4.4 節は、代行者に関連する JWT クレームを定義しています。

トークンタイプ

これらのトークンが取りうる型として、仕様は次のトークンタイプを列挙し、それぞれにトークンタイプ識別子を割り当てています。これらのトークンタイプ識別子は IANA (Internet Assigned Numbers Authority) の OAuth Parameters / OAuth URI に登録されています。
JWT 用のトークンタイプ識別子は RFC 7519 JSON Web Token (JWT) で定義されています。他の識別子は RFC 8693 OAuth 2.0 Token Exchange で定義されています。

トークン交換リクエスト

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

グラントタイプ

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

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

仕様自体は、トークンエンドポイントにおけるクライアント認証やクライアントの特定を要求していません。これについて RFC 8693Section 2.1. Request は次のように述べています。
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 Section 2.1. Client Types)、『未特定のクライアント』はトークンリクエストがクライアントを特定するための情報を含んでいないことを意味します。 RFC 8693付録 1.1 には特定不能なクライアントからのトークン交換リクエストの例が示されていますが、このようなケースは、サービス内の閉じた環境のような、特定の条件下に限られます。それ以外の場合には、安全なトークン交換のための詳細仕様化を行い、RFC 8693 を補完する必要があります。

リクエストパラメーター

トークン交換リクエストに関連するパラメーターを以下に示します。
RFC 6749 The OAuth 2.0 Authorization Framework は “Request and response parameters MUST NOT be included more than once.” (リクエストパラメーターとレスポンスパラメーターは複数回含まれていてはならない) と述べています。resource リクエストパラメーターと audience リクエストパラメーターは例外です。

トークン交換レスポンス

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

レスポンスパラメーター

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

Authlete における対応

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

トークン交換リクエスト

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

クライアントからトークンリクエストを受信した認可サーバーは、そのリクエストの内容を Authlete の /auth/token API に引数として送信します。同 API は与えられたトークンリクエストに関し、
  • grant_type パラメーターの値が urn:ietf:params:oauth:grant-type:token-exchange であり、かつ
  • そのリクエストが Authlete サーバー側で実行される基本的なバリデーション処理をパスした
場合に、action パラメーターの値として TOKEN_EXCHANGE を含むレスポンスを返却します。 その他、/auth/token API からのレスポンスに含まれるトークン交換関連のパラメーターを、次の表に示します。

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

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

トークンタイプ: JWT

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

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

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

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

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

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

暗号化された ID トークン用のクライアント ID を決定することができないトークン交換の文脈においては、ID トークンの復号化に使う鍵を取得する標準的な方法が存在しないため、Authlete は暗号化された ID トークンのバリデーションをおこないません。これは、暗号化された ID トークンがトークンタイプ urn:ietf:params:oauth:token-type:id_token の入力トークンとして用いられた場合、(サービスの tokenExchangeEncryptedJwtRejected フラグが false の場合) あなた自身で暗号化された ID トークンのバリデーションを実施しなければならないということを意味します。
上述の 10 番目のバリデーション処理は、署名アルゴリズムが対称鍵系 (HS256HS384 または HS512) の ID トークンをトークンタイプ urn:ietf:params:oauth:token-type:id_token のサブジェクトトークンやアクタートークンとして用いることができないことを示唆しています。トークン交換の文脈においては、署名検証に使う対称鍵 (つまりクライアントシークレット) を決定できないからです。
ID トークンの発行者があなたのサービスではない場合でも署名検証は実行されます。ただしその場合、発行者は OpenID Connect Discovery 1.0 で定義されているディスカバリーエンドポイントをサポートしなければなりません。サポートしていない場合、署名検証は失敗します。

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

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

トークン交換レスポンス

/auth/token/create API

認可サーバーは、/auth/token API からのレスポンスに基づいて必要なバリデーションを行い、どのようなトークンを発行するかを決定した後に、トークン交換レスポンスをクライアントに返却します。 トークン交換レスポンスの生成には Authlete の /auth/token/create API を用います。その際、この API のリクエストパラメーターのうち、grantType の値に TOKEN_EXCHANGE を指定します。

関連する設定項目

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

サービス設定

クライアント拡張設定

利用例

認可サーバー実装の例

TOKEN_EXCHANGE アクションの処理

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

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

Java で書かれたオープンソースの認可サーバー実装サンプルである java-oauth-serverTokenExchanger.java が、トークン交換リクエスト処理の実装サンプルとなっています。 なお当実装は一例に過ぎず、商用利用可能な完璧さは意図していないことにご注意ください。

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

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

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

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

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