Skip to main content
Authlete 2.x のドキュメントは 2.x 版をご覧ください。

はじめに

このドキュメントでは、Authlete を利用した Financial-grade API Security Profile 1.0 - Part 2: Advanced (以下 FAPI)対応のアイデンティティ・プロバイダーを構築する手順を通じて、同仕様が規定するセキュリティ条項の概要と Authlete の設定方法を紹介します。 手順の実施にあたっては、以下のチュートリアルとナレッジベース記事を通読し、 OpenID Connect と Authlete に関する基本的な理解を有していることが必須です。

構成

本チュートリアルでは以下の構成を想定します。 なお、実サービスとして動作するのは、Authlete のコンソールと API だけです。 認可サーバー(OIDC アイデンティティプロバイダー)とリソースサーバーはいずれも実際には存在しませんが、 それぞれのサーバーがクライアント(OIDC リライングパーティ)から認可リクエストやトークンリクエスト、そしてトークンイントロスペクションリクエストを受信したときに、 どのような API リクエストを Authlete に行うかを、curl コマンドを用いて試行します。 チュートリアルにおける各要素の構成 チュートリアルにおける各要素の構成
本チュートリアルでは便宜上、OIDC アイデンティティプロバイダーを「認可サーバー」、同リライングパーティを「クライアント」と表記します。
各サービスの FQDN は以下の通りです。上述の通り認可サーバーとクライアントは存在しませんが、OAuth のフローを説明する上で FQDN が最低限必要となります。
Authlete 3.0 の API ホストはサービスが属するクラスターによって決まります。本チュートリアルでは US クラスター (us.authlete.com) を前提に記述しています。日本クラスターの場合は jp.authlete.com に読み替えてください。値はコンソールのサービス概要にある「クラスターURL」で確認できます。

FAPI を用いた API クライアントと API サーバーとの間のやりとり

本ドキュメントでは、FAPI に準拠した以下のトークン授受・利用フローに対応するための設定を行います。 FAPI 準拠のトークン授受・利用フロー FAPI 準拠のトークン授受・利用フロー

1. 認可リクエスト (Authorization Request)

クライアントはリクエストオブジェクトを用いた認可リクエストを作成・送信する必要があります。 リクエストオブジェクトは値渡し(request パラメーターを使用)もしくは参照渡し(request_uri パラメーターを使用)のいずれかとなります。本ドキュメントでは前者を用います。
参照渡しの場合には Pushed Authorization Requests (PAR) の利用を推奨します。
また、response_type パラメーターの指定についても FAPI の規定に従う必要があります。 response_type として本ドキュメントでは code id_token を用います。
response_type として code を用いる場合には、JARM (JWT Secured Authorization Response Mode for OAuth 2.0) の設定が必要です。
その他、claims の設定などについては後述します。

2. 認可レスポンス (Authorization Response)

本ドキュメントでは、認可リクエストに response_type=code id_token が指定されることから、フラグメントとして code を返却します。

3. トークンリクエスト (Token Request)

トークンリクエストでは、認可サーバーはクライアントを認証する方法として公開鍵方式を用いる必要があります。 本ドキュメントでは TLS 双方向認証を用います。

4. トークンレスポンス (Token Response)

認可サーバーは、トークンエンドポイントに提示されるクライアント証明書と、発行するアクセストークンとをバインド(ひもづけ)し、トークンレスポンスを返却します。

5. API リクエスト (API Request)

クライアントとリソースサーバーは、TLS 双方向認証を用いてクライアント認証を行った上で、アクセストークンを含む API リクエストを送受信します。 リソースサーバーはクライアント証明書とアクセストークンとのひもづけを検証の上、API レスポンスを返却します。

初期設定

新規サービスとそのクライアントの追加

サービスの追加と FAPI の有効化

Authlete 管理コンソールにログインし、対象の組織を開いて「サービスを新規作成」をクリックします。 サービスの新規作成ページが表示されるので、以下を入力・選択して「作成」をクリックします。 サービスの新規作成 サービスの新規作成
「指定可能なサービスプロファイル (任意)」を有効にすると、このサービスが FAPI プロファイルをサポートするようになります。これは FAPI の機能を使うための前提条件です。既存のサービスで後から有効にする場合は、サービス設定の「エンドポイント > 詳細設定 > FAPI」タブで同じ項目を切り替えます。
作成したサービスの「サービス概要」には「サービスID」と「クラスターURL」が表示されます。以降の curl 例で使うため控えておきます。 また、Authlete API を呼び出すための「サービスアクセストークン」を発行します。手順は Authlete のセットアップの「サービスアクセストークンの取得」を参照してください。 サービス設定の「エンドポイント > 詳細設定 > FAPI」タブを開くと、FAPI に関する設定項目を確認できます。 サービス設定の「FAPI」タブ サービス設定の「FAPI」タブ
「FAPI モード」を選択すると、このサービスへのすべてのリクエストがそのモードで処理されます。本チュートリアルではリクエストのスコープに応じて FAPI 準拠の処理を適用するため、「FAPI モード」は「なし」のままにします。判定の順序については FAPI の機能を利用するをご参照ください。
次に、FAPI 対象のスコープを作成します。 サービス設定の「トークン&クレーム > 詳細設定 > スコープ」タブを開き、「サポートするスコープ」の「追加」をクリックすると、スコープの追加ダイアログが表示されます。 ここでは以下の内容のスコープを作成し、「追加」をクリックしたのち「変更を保存」で保存します。
あるスコープの属性として、キー: fapi、値: rw を追加すると、Authlete はそのスコープが要求された場合に FAPI 準拠の処理を行います。スコープ属性についてはスコープの属性をご参照ください。
スコープの追加 スコープの追加

クライアントの追加と基本設定

サービスの「クライアント」ページで「クライアントを新規作成」をクリックし、以下を入力・選択して「作成」をクリックします。 クライアントの新規作成 クライアントの新規作成 作成後、クライアント設定の「エンドポイント > 基本設定 > リダイレクトURI」で以下を追加し、「変更を保存」をクリックします。 これにより、サービスへのクライアント情報の登録が完了しました。 自動生成された「クライアントID」は、クライアントが認可サーバーにリクエストを行う際の client_id の値として用いられます。 なお、同時に「クライアントシークレット」も生成されていますが、本チュートリアルでは使いません。

初期設定後の動作確認

/auth/authorization API /auth/authorization API 上記の設定によって Authlete がどのように動作するかを、まず /auth/authorization API を用いて確認します。 以降の curl 例では、{サービス ID}{サービスアクセストークン}{クライアント ID} を、ここまでの手順で取得した値に置き換えてください。

非 FAPI スコープに関する認可リクエスト

認可サーバーが、FAPI 対象のスコープが含まれない (scope=openid のみの) 認可リクエストを受信したと仮定し、 /auth/authorization API に対して以下のリクエストを送信します。
すると、以下のようなレスポンス(一部折り返しています)が返却されます。
resultMessage の記述から、scope=openid のように、FAPI 対象ではないスコープの場合には、認可リクエストが Authlete に受け入れられたことがわかります。 それでは、FAPI の対象となるスコープの場合にはどのようになるか、次に試してみます。

FAPI スコープに関する認可リクエスト (1)

認可サーバーが、FAPI 対象のスコープ(payment)を含む認可リクエスト(scope=openid payment)を受信したと仮定し、 /auth/authorization API に対して以下のリクエストを送信します。
すると、以下のようなエラーレスポンスが返却されます。
resultMessage の内容を見ると、response_type=code は許可されていないことがわかります。 これは FAPI の 5.2. Advanced security provisions / 5.2.2. Authorization server
  • shall require
    1. the response_type value code id_token, or
    2. the response_type value code in conjunction with the response_mode value jwt;
とある通り、FAPI では response_type=code id_token か、もしくは response_mode=jwt を指定した上で response_type=code の、どちらかを用いなくてはならないからです。 つまり response_type=code のみの指定は禁止されている(認可サーバーはそのようなレスポンスタイプを受け付けてはならない)のです。

FAPI スコープに関する認可リクエスト (2)

それでは、response_type=code ではなく response_type=code id_token とした認可リクエストの場合にはどうなるでしょうか。 /auth/authorization API に対して以下のリクエストを送信します。
すると以下のような異なるエラーレスポンスが返却されます。
resultMessage の記述から、この場合には、リクエストオブジェクトが必要だとわかります。 これは上述と同じく、FAPI の 5.2. Advanced security provisions / 5.2.2. Authorization server
  • shall only use the parameters included in the signed request object passed via the request or request_uri parameter;
とある通り、FAPI では、認可サーバーはクライアントに対して、リクエストオブジェクトを値渡し(request)ないし参照渡し(request_uri)にて認可リクエストに含めるよう、 要求しなくてはならないからです。 それでは次に、リクエストオブジェクトを用いた認可リクエストを準備してみましょう。

認可リクエストの FAPI 対応

本セクションでは、リクエストオブジェクトを用いた認可リクエストを作成します。

リクエストオブジェクトの設定

リクエストオブジェクトの署名鍵の設定

まず、クライアントがリクエストオブジェクトに署名するための鍵を準備します。 ここでは例として、mkjwk を用いて、ES256 の鍵ペアを生成し、 2 種類(秘密鍵を含むもの・含まないもの)の鍵セットを生成します。 パラメーターは以下の通り選択・入力しています。 mkjwk を用いた JWK セット生成 mkjwk を用いた JWK セット生成 以下は生成された鍵セットの例です。
  • es256_keyset.txt (秘密鍵 "d" の行を含む)
  • es256_keyset_pub.txtes256_keyset.txt から秘密鍵 "d" の行を削除)

クライアント設定の追加

Authlete サービスに、クライアントから受信したリクエストオブジェクトの署名を検証させるためには、 そのクライアントの設定として公開鍵を登録し、さらに署名アルゴリズムを指定する必要があります。 まず、クライアント設定の「キーマネジメント > JWKセット」を開き、以下を設定して「変更を保存」をクリックします。 クライアント設定の「JWKセットの内容」 クライアント設定の「JWKセットの内容」 次に、クライアント設定の「エンドポイント > 認可 > リクエストオブジェクト」を開き、以下を設定して「変更を保存」をクリックします。 クライアント設定の「リクエストオブジェクト」 クライアント設定の「リクエストオブジェクト」 上記の設定により、リクエストオブジェクトの署名検証の準備が整いました。

リクエストオブジェクトの生成

ここではリクエストオブジェクトを作成し、認可リクエストを組み立てます。 まず、以下のペイロードを準備します。client_id, nbf, exp の値は適宜変更します。 payload.txt
以下は nbfexp の値の生成例です。
  1. nbf クレーム: date +%s などを実行して現在時刻の Unix time を取得し、それを nbf クレームの値としてペイロードに追加します。たとえば date +%s の結果が 1613373232 である場合には、payload.txt に追加する行は "nbf":1613373232, です。
  2. exp クレーム: nbf3600 を加えた値を、exp に指定します。たとえば "nbf":1613373232 である場合には、1613373232 + 3600 = 1613376832 となり、payload.txt の当該行の修正は "exp":1613376832, です。
秘密鍵を用いて Signed JWT を作成します。 以下は mkjose を用いて作成する例です。 各項目を入力・選択し、「生成する」ボタンを押下すると、「結果」の欄に Signed JWT が出力されます。 mkjose を用いた Signed JWT の生成 mkjose を用いた Signed JWT の生成 また、step CLI を用いて作成する場合には以下の例のようになります。
以下は実行結果の例です。この文字列を、認可リクエストの request パラメーターの値として用います。

動作確認

認可サーバーが認可リクエストをクライアントから受信したと仮定し、 Authlete の /auth/authorization API に対して以下のリクエストを送信します。
すると、以下のようなレスポンス(一部折り返しています)が返却されます。
resultMessage の記述から、リクエストが受理されたことがわかります。 そして期待した通り、ticket が返却されています。 認可サーバーはこの ticket の値をログインセッションに格納し、 ユーザー認証と同意確認を行い、そして Authlete の /auth/authorization/issue API を呼び出し、 認可レスポンスの生成を要求することになります。 本ドキュメントの手順では、認可リクエストに response_type=code id_token と指定しています。 よって認可レスポンスは、認可コード code と ID トークン id_token を、フラグメントとして含むものになります。 /auth/authorization/issue API /auth/authorization/issue API 認可サーバーがユーザー認証と同意確認を行い、その結果決定したユーザー識別子(subject)が testuser01 であったと仮定し、 /auth/authorization/issue API にリクエストを送信してみましょう。 この subject と、上記の ticket が、API リクエストの引数となります。
すると、以下のようなレスポンス(一部折り返しています)が返却されます。
resultMessage の記述から、現在設定されている(Authlete の既定値である)HS256 が、ID トークンの署名アルゴリズムとして許可されていないことがわかります。 これは FAPI の 8.6. Algorithm considerations
  • shall use PS256 or ES256 algorithms;
とある通り、クライアントと認可サーバーは JWS アルゴリズムとして ES256 もしくは PS256 のどちらかを用いなければならないからです。 本ドキュメントでは、認可サーバーが ID トークンの署名アルゴリズムとして ES256 を用いるように、Authlete を設定してみます。

認可レスポンスの FAPI 対応

ID トークンの署名アルゴリズムの変更

ID トークンの署名鍵の追加

ES256 の鍵セットを生成し、ID トークンの署名に用いる鍵としてサービスに登録するとともに、 クライアント設定として ID トークンの署名アルゴリズムに ES256 を指定します。 手順の詳細は ID トークンの署名鍵の変更を参照してください。
このセクションにて生成する鍵セットは、認可サーバーが ID トークンの署名に用いるためのものです。 一方、先の「リクエストオブジェクトの署名鍵の設定」において生成・登録した鍵セットは、 クライアントから受け取ったリクエストオブジェクトの署名を認可サーバーが検証するためのものです。 両者を混同しないようにご注意ください。
本ドキュメントでは、以下のパラメーターを選択・入力します。 生成された鍵セット(“Keypair set”)を、まずサービスに登録します。 サービス設定の「キーマネジメント > JWKセット > 認可サーバー」を開き、以下を設定して「変更を保存」をクリックします。 サービス設定の「JWKセットの内容」「IDトークン署名キーID」 サービス設定の「JWKセットの内容」「IDトークン署名キーID」 次に、クライアント設定の「トークン&クレーム > IDトークン」を開き、「IDトークンアルゴリズム」の「署名アルゴリズムを選択」で ES256 を選択して「変更を保存」をクリックします。 この設定により Authlete は、このクライアントに対して ID トークンを発行する際の署名アルゴリズムとして ES256 を用いるようになります。 クライアント設定の「IDトークンアルゴリズム」 クライアント設定の「IDトークンアルゴリズム」

動作確認

変更後、ticket 生成から再度動作確認を行います。 まず /auth/authorization API を実行します。
この処理結果(一部折り返しています)として ticket が返却されます。
返却された ticketsubject の値を用いて、/auth/authorization/issue API にリクエストを行います。
すると、以下のようなレスポンス(一部折り返しています)が返却されます。
resultMessage の記述から、認可リクエストの処理に成功したことがわかります。また idToken, authorizationCode にそれぞれ値が返却されています。 そして responseContent として、認可サーバーがクライアントに返却する HTTP レスポンスが生成されており、レスポンスのフラグメント部に ID トークンと認可コードが含まれていることがわかります。 この後クライアントは ID トークンを検証し、さらにその中に含まれる c_hash クレームを用いて認可コードを検証したのちに、 認可サーバーにトークンリクエストを送信することになります。そして認可サーバーはそのトークンリクエストを Authlete の /auth/token API に送信し、 アクセストークンを含むトークンレスポンスの生成を要求します。 /auth/token API /auth/token API /auth/token API に対するリクエストは以下の通りです。
すると、以下のようなレスポンス(一部折り返しています)が返却されます。
resultMessage の記述から、コンフィデンシャルクライアントのクライアント認証として、 Authlete の既定値である none は許可されていないことがわかります。 これは FAPI の 5.2 Read and write API security provisions / 5.2.2. Authorization server
  • shall authenticate the confidential client using one of the following methods (this overrides FAPI Security Profile 1.0 - Part 1: Baseline clause 5.2.2-4):
    1. tls_client_auth or self_signed_tls_client_auth as specified in section 2 of MTLS, or
    2. private_key_jwt as specified in section 9 of OIDC;
とある通り、FAPI では RFC 8705 が定義する Mutual TLS for OAuth Client Authentication、もしくは OpenID Connect Core 1.0 が定義する private_key_jwt のどちらかを用いなくてはならないからです。つまり none や、コンフィデンシャルクライアントの場合に広く使われている client_secret_basic は禁止されている(認可サーバーはそのようなクライアント認証を行ってはならない)のです。 本ドキュメントでは前者、かつ PKI Mutual-TLS Method (tls_client_auth) を用いるように Authlete を設定してみます。
private_key_jwt を用いる場合には private_key_jwt によるクライアント認証をご参照ください。なお、同クライアント認証手段を用いた場合にも、「Holder of Key」を実現するための TLS 双方向認証の設定は同時に必要となります。

トークンリクエストの FAPI 対応

TLS クライアント認証の設定

クライアント認証に「TLS クライアント認証」を用いるように、サービスおよびクライアントの設定を変更します。

サービス側の TLS クライアント認証設定

サービス設定の「エンドポイント > トークン」を開き、「サポート可能なクライアント認証方式」で以下を選択して「変更を保存」をクリックします。 サービス設定の「サポート可能なクライアント認証方式」 サービス設定の「サポート可能なクライアント認証方式」

クライアント側の TLS クライアント認証設定

クライアント設定の「エンドポイント > トークン > MTLS」を開き、以下を設定して「変更を保存」をクリックします。 クライアント設定の「サブジェクト識別名」 クライアント設定の「サブジェクト識別名」 続いてクライアント設定の「エンドポイント > トークン」を開き、以下を設定して「変更を保存」をクリックします。 クライアント設定の「クライアント認証方式」 クライアント設定の「クライアント認証方式」 以上の設定により、Authlete サービスは TLS 双方向認証によるクライアント認証に対応し、かつ上記のクライアントからのトークンリクエストについて、その認証方式を適用することになります。 また認証の際のクライアント識別名として CN=client.example.org, ... を用います。

自己署名証明書の生成

クライアントが自身の認証に用いる証明書を作成します。以下は openssl を用いて作成する例です。
  • 秘密鍵の生成
  • CSR の作成(Subject DN として CN=client.example.org, O=Client, L=Chiyoda-ku, ST=Tokyo, C=JP を指定)
  • 証明書の作成
curl コマンドを用いてリクエストを行う際には、生成された server.crt の内容を 1 行で表現したもの(改行を \n に置き換えたもの)を用います。

動作確認

サービス設定とクライアント設定をそれぞれ変更したのちに、以下の手順を実行します。
  1. /auth/authorization API を実行し、レスポンスから ticket の値を取得
  2. /auth/authorization/issue API を実行し、レスポンスから authorizationCode の値を取得
  3. 以下を変更の上、/auth/token API を実行
    • clientCertificate パラメーターを追加し、値としてクライアント証明書を指定する
    • clientSecret パラメーターを削除する(TLS 双方向認証を用いるため不要となります)
以下は /auth/token API に送信するリクエストの例です。
すると、以下のようなレスポンス(一部折り返しています)が返却されます。
resultMessage の記述から、アクセストークンは発行されたものの、未だ設定が不足しているために、 FAPI 仕様上必須である「Holder of Key」が行われなかったことがわかります。 すなわち、ここまでの手順だけでは、 TLS クライアント証明書をひもづけたアクセストークン発行の処理が行われていないということです。

トークンレスポンスの FAPI 対応

Holder of Key の設定

サービス側のアクセストークン設定

サービス設定の「トークン&クレーム > アクセストークン」を開き、以下を設定して「変更を保存」をクリックします。 サービス設定の「相互TLSクライアント証明書バインディング」 サービス設定の「相互TLSクライアント証明書バインディング」

クライアント側のアクセストークン設定

クライアント設定の「トークン&クレーム > アクセストークン」を開き、以下を設定して「変更を保存」をクリックします。 クライアント設定の「TLSクライアント証明書バインディング」 クライアント設定の「TLSクライアント証明書バインディング」 以上により、FAPI 準拠の認可サーバーの設定が完了しました。

設定完了後の実行例

FAPI 準拠のトークン授受・利用フロー(Authlete を利用) FAPI 準拠のトークン授受・利用フロー(Authlete を利用) 変更後、先と同様の手順により /auth/authorization API/auth/authorization/issue API/auth/token API を実行します。 さらに /auth/introspection API を実行して、最終的に API リクエストに用いられるアクセストークンが、クライアントの TLS クライアント証明書に紐づけられていることを確認します。

認可リクエスト

  • レスポンス(一部折り返しています)

認可レスポンス

  • レスポンス(一部折り返しています)

トークンリクエスト/レスポンス

  • レスポンス(一部折り返しています)

API リクエスト

上記手順の結果、アクセストークンとして SUtEVc3Tj3D3xOdysQtssQxe9egAhI4fimexNVMjRyU が生成されています。 この値をリソースサーバーがクライアントから受信したと仮定し、/auth/introspection API を用いて、 このアクセストークンの有効性と、関連する情報の取得を試みます。 この際に、リソースサーバーがクライアントから同時に受け取るであろう、クライアント証明書も併せて API に送信します。 /auth/introspection API /auth/introspection API
  • レスポンス(一部折り返しています)
certificateThumbprint が返却されていることから、このアクセストークンがクライアント証明書にひもづけられていることがわかります。 これによりリソースサーバーは、クライアントから受信したアクセストークンの有効性を確認し、そのトークンにひもづいている情報を取得することができました。

まとめ

本チュートリアルでは、FAPI に準拠したトークン授受・使用に対応した認可サーバーを構築するための、Authlete の設定を行いました。