はじめに
この文書は Authlete ベースの認可サーバー (AS) と外部のアイデンティティプロバイダー (IdP) との連携方法を説明するチュートリアルです。この連携により、Financial-grade API (FAPI) のような高いセキュリティの業界標準に準拠した API 認可基盤を構築すると同時に、外部 IdP のユーザー認証・管理機能を利用できるようになります。 この連携のしくみは、ユーザーの認証情報や属性情報などを IDaaS (Identity as a Service) を用いて既に維持管理しているサービス事業者が、英国オープンバンキング / オーストラリア消費者データ権 / ブラジルオープンバンキングなどのエコシステムが定義する FAPI ベースのセキュリティ要件を実装しなければならない場合に有用です。 このチュートリアルでは、OpenID Connect (OIDC) IdP として Okta、Authlete を利用する AS として java-oauth-server を用い、連携方法の例を説明します。前提条件
このチュートリアルを始める前に次のアカウントを用意しておいてください。- Authlete アカウント (参照→『サインアップから Authlete サービス作成までの手順』)
- Okta アカウント (参照→ Okta ウェブサイト)
AS と IdP の連携
OAuth 2.0 (RFC 6749) と OIDC (OpenID Connect Core 1.0) の仕様は、AS がユーザーをどのように認証するかについては意図的に定義していません。そのため AS は、ユーザー認証を外部 OIDC IdP に委譲し、当 IdP からユーザー情報を取得するという手段をとるかもしれません。下図は、そのような AS と外部 OIDC IdP との間の、アイデンティティ (ID) 連携のフローを示しています。
- クライアントアプリケーションがウェブブラウザ経由で AS の認可エンドポイントに認可リクエストを送る。
- AS の認可エンドポイントは認可ページを生成してウェブブラウザに返す。AS が外部 IdP との ID 連携をサポートしていれば、認可ページに ID 連携用のリンクが含まれる。
- 表示された認可ページ内の ID 連携用のリンクをユーザーがクリックする。この操作により、選択された IdP との ID 連携を開始する Web API (図中の「(フェデレーション/開始)」) にウェブブラウザがアクセスする。
- Web API は OpenID Connect に準拠する認証リクエストを作成する。認証リクエストは IdP の認可エンドポイントを指す URL で、クエリー部にリクエストパラメーター群を含む。
- Web API は
Locationヘッダーをつけて302 Found(リダイレクションを促すものであれば何でもよい) をウェブブラウザに返す。これによりウェブブラウザは IdP の認可エンドポイントに認証リクエストを送ることになる。 - ウェブブラウザが IdP の認可エンドポイントに認証リクエストを送る。
- IdP の認可エンドポイントは認可ページを生成してウェブブラウザに返す。その認可ページは、「(クライアントではなく) AS が権限を要求している」とユーザーに伝える。
- ユーザーは IdP で自身のユーザー認証をおこない、AS からの認証リクエストを承認する。
- IdP は認可コードを生成し、
Locationヘッダーをつけて302 Found(リダイレクションを促すものであれば何でもよい) をウェブブラウザに返す。これによりウェブブラウザは (クライアントのものではなく) AS のリダイレクション URI に認可コード付きでアクセスする。IdP の視点からは、AS はクライアントアプリケーションであり、当該リダイレクション URI は AS が事前に IdP に登録しておいたものの一つである。 - AS のリダクレションエンドポイント (図中の「フェデレーション/コールバック」) が認可コードを受け取る。
- リダイレクションエンドポイントは、IdP のトークンエンドポイントに、受け取った認可コードを含むトークンリクエストを送る。
- IdP のトークンエンドポイントはアクセストークンと ID トークンを生成して返す。
- リダイレクションエンドポイントは返却されたアクセストークンを添えて IdP のユーザー情報エンドポイントにアクセスする。
- IdP のユーザー情報エンドポイントはユーザーの情報を返す。
- リダイレクションエンドポイントはユーザーが AS にログインしたとみなし、認可ページを再生成してウェブブラウザに返す。
- ユーザーはクライアントからの当初の認可リクエストを承認する。
- AS は認可コードを生成し、
Locationヘッダーをつけて302 Found(リダイレクションを促すものであれば何でもよい) をウェブブラウザに返す。これによりウェブブラウザは (AS のものではなく) クライアントのリダイレクション URI に認可コード付きでアクセスする。ここではクライアントが少なくとも一つのリダイレクション URI を事前に AS に登録済みであることを想定している。 - クライアントのリダクレションエンドポイント (図中の「リダイレクションエンドポイント」) が認可コードを受け取る。
- クライアントはリダイレクションエンドポイント経由で受け取った認可コードを添えて AS のトークンエンドポイントにアクセスする。
- AS のトークンエンドポイントはアクセストークンを生成してクライアントに返す。
IdP (Okta) の設定
OIDC 互換 IdP のクライアントアプリケーションとして AS が動作できるよう、Okta 上で稼働するサーバーに「App Integration」を作成する必要があります。 下表は App Integration 設定の要点を示しています。| 項目 | 値 |
|---|---|
| Sign-in method | OIDC - OpenID Connect |
| Application Type | Web Application |
| Sign-in redirect URIs | http://localhost:8080/api/federation/callback/okta |
| Controlled access | Allow everyone in your organization to access |
/api/federation/callback/okta API を提供します。
次の画像群は App Integration 設定のスクリーンショットです。




AS (java-oauth-server) の設定
このチュートリアルでは java-oauth-server を AS として用います。java-oauth-server はオープンソースの AS サンプル実装で、Authlete をバックエンドとして利用します。 まず初めに java-oauth-server をダウンロードしてauthlete.properties を編集してください。少なくとも同ファイル内の service.api_key と service.api_secret の値を変更する必要があります。
federations.json をテキストエディタで開いてください。このファイルに ID 連携の設定を記述します。内容の初期値は下記のようになっています。YOUR_COMPANY、YOUR_CLIENT_ID、YOUR_CLIENT_SECRET を Okta から割り当てられた実際の値で置き換えてください。federations.json の詳細については「付録 / federations.json」を参照してください。
動作確認
「 AS と IdP の ID 連携」で示した図では、クライアントは OIDC 認可コードフロー (response_type=code) を用いています。しかしここでは、Okta との ID 連携が機能していることを素早く確認するため、ID トークンのみを発行する OIDC インプリシットフロー (response_type=id_token) を使用します。
次の URL は認可リクエストです。CLIENT_ID をAuthlete から発行されたクライアント ID (Okta から発行されたものではない)、SERVICE_API_KEY を Authlete から発行されたサービス API キーで置き換え、URL をウェブブラウザのアドレスバーに貼り付けてください。



/api/mock/redirection/サービスAPIキー) は受け取ったパラメーター群を表示します。
リクエストに暗号化されていない ID トークンが含まれていれば、リダイレクションエンドポイントはその ID トークンのペイロード部をデコードし、次のように表示します。

| クレーム | データ提供元 |
|---|---|
email | Okta |
email_verified | Okta |
family_name | Okta |
given_name | Okta |
locale | Okta |
name | Okta |
phone_number_verified | Okta |
preferred_username | Okta |
updated_at | Okta |
zoneinfo | Okta |
iss | Authlete / Service 設定, issuer |
sub | java-oauth-server / Authlete の /api/auth/authorization/issue API に渡された subject パラメーター |
aud | Authlete / Client 設定, clientId (変更不可) |
exp | Authlete / ID トークンの有効期間終了時刻 |
iat | Authlete / ID トークンの発行時刻 |
auth_time | java-oauth-server / Authlete の /api/auth/authorization/issue API に渡された authTime パラメーター |
nonce | クライアント / nonce リクエストパラメーターの値 |
s_hash | Authlete / state リクエストパラメーターの値に基づいて計算 |
sub クレームの値 (例内の "00ucabhbjLVphPrXF696@okta") がどこから来たのか気になられるかもしれません。この値は、Okta が返した sub クレームの値と文字列 "@okta" を連結した結果に過ぎません。連結は FederationEndpoint.java の createUserEntity() メソッドで実行されています。これに大きな意味はなく、sub クレームの値をどのように決めるかはあなた次第です。
まとめ
本チュートリアルでは、Authlete ベースの認可サーバー (AS) と外部のアイデンティティプロバイダー (IdP) との連携パターンを、java-oauth-server と Okta を用いて、実際の動作を確認しました。付録
実装の詳細
ID 連携の実装レベルの詳細については java-oauth-server の Federation.java と FederationEndpoint.java を調べることで理解できます。 OIDC IdP のユーザー情報エンドポイントからユーザー情報を受け取ったあと、java-oauth-server の現実装はメモリ上のユーザーデータベースにユーザーレコードを登録します。しかし、商用実装では他の選択肢もありうるでしょう。 例えば、OIDC IdP から得たユーザーデータを手元のデータベースに複製することを避け、かわりに IdP から発行されたアクセストークンを覚えておき、後ほど好きな時に IdP のユーザー情報エンドポイントから最新のユーザー情報を取り出せるようにするかもしれません。 そのような動作を実装するため、AS は IdP から発行されたアクセストークンを覚えておくデータベースを用意するかもしれません。その他にも、アクセストークンに任意のキー・バリュー群を関連付ける Authlete 独自の Extra Properties 機能を用い、IdP が発行したアクセストークンを Authlete に覚えておかせるという方法も考えられます (参照→『トークンに任意のプロパティをひもづける方法』)。federations.json
federations.json は ID 連携の設定を記述するための設定ファイルです。java-oauth-server は最初に認可リクエストを受け取ったときに当ファイルを読み込みます。ファイル内に列挙された ID 連携は java-oauth-server の認可ページ内に表示されます。
ファイルのデフォルトの位置は "fderations.json" です。環境変数 FEDERATIONS_FILE およびシステムプロパティー federations.file を用いて他の場所を指定することができます。
federations.json の内容は、"federations" を最上位プロパティーとして持つ JSON オブジェクトでなければなりません。
"federations" 配列の各要素は ID 連携の設定を表し、"id"、"server"、"client" を最上位プロパティーとして持つ JSON オブジェクトです。
"id" の値は、java-oauth-server の次の API パス内の federationId 部で使用されます。
/api/federation/initiation/federationId/api/federation/callback/federationId
"server" には対象の IdP の設定を記述します。値は JSON オブジェクトで、下表のプロパティー群を持ちます。
| プロパティー | 説明 |
|---|---|
name | IdP の表示名。認可ページで利用されます。 |
issuer | IdP の発行者識別子。この値は IdP のディスカバリードキュメント内の "issuer" の値と一致していなければなりません。java-oauth-server の ID 連携を機能させるためには、IdP が {issuer}/.well-known/openid-configuration でディスカバリードキュメントを公開していなければなりません。 |
"client" はクライアントの設定を記述するもので、ここでクライアントは常に java-oauth-server を指します。外部 IdP から見ると java-oauth-server はクライアントアプリケーションであることに留意してください。"client" の値は JSON オブジェクトで、下表のプロパティー群を持ちます。
| プロパティー | 説明 |
|---|---|
clientId | IdP が発行したクライアント ID。 |
clientSecret | IdP が発行したクライアントシークレット。このプロパティーがセットされている場合、IdP のトークンエンドポイントに送られるトークンリクエストにクライアント認証用の Authorization ヘッダーが含まれるようになります。この動作はトークンエンドポイントがクライアント認証方式として client_secret_basic をサポートしていることを前提としています。 |
redirectUri | IdP に事前登録してあるリダイレクション URI。 |
idTokenSignedResponseAlg | IdP が ID トークンに署名する際に使用するアルゴリズム。このプロパティーが省略された場合、デフォルト値として "RS256" が使用されます。 |