FAPI(Financial-grade API)セットアップ
このドキュメントの目的
FAPI 1.0 準拠の認可サーバー設定を行い、金融グレードのセキュリティを実現することが目標です。 OIDF(OpenID Foundation)適合性テストに合格するための設定パラメータについても解説します。
所要時間
⏱️ 約30分
前提条件
- テナント作成が完了済み
- クライアント登録が完了済み
- mTLS対応の環境構築(リバースプロキシまたはロードバランサーでクライアント証明書を処理)
- 管理者トークンを取得済み
FAPIとは
FAPI(Financial-grade API) は、OpenID Foundationが策定したOAuth 2.0 / OpenID Connectのセキュリティプロファイルです。金融APIをはじめとする高セキュリティが求められるAPIを保護するための追加要件を定義しています。
セキュリティレベル:
OAuth 2.0(基本)
└─ OpenID Connect(認証追加)
└─ FAPI 1.0 Baseline(セキュリティ強化)
└─ FAPI 1.0 Advanced(最高レベル)
FAPI 1.0 Baseline と Advanced の違い
| 要件 | Baseline | Advanced |
|---|---|---|
| PKCE S256 必須 | 常に必須 | PAR使用時に必須 |
| クライアント認証制限 | client_secret_basic/post 禁止 | + client_secret_jwt も禁止 |
| redirect_uri https必須 | 必須 | 必須 |
| nonce 必須(openid scope時) | 必須 | 必須 |
| state 必須(openid scope なし時) | 必須 | 必須 |
| Request Object (署名付きJWT) | 不要 | 必須 |
| 署名アルゴリズム制限 (PS256/ES256) | なし | 必須 |
| Request Object の nbf/exp/aud | 不要 | 必須 |
| Sender-Constrained Access Token (mTLS) | 不要 | 必須 |
| Public Client 禁止 | なし | 禁止 |
| JARM (JWT応答モード) | 不要 | code + jwt で必須 |
FAPIプロファイルの決定メカニズム
idp-serverでは、リクエストに含まれるscopeの値に基づいてFAPIプロファイルが自動選択されます。
リクエストの scope 値
↓
scope ∩ fapi_advance_scopes ≠ ∅ → FAPI_ADVANCE プロファイル
scope ∩ fapi_baseline_scopes ≠ ∅ → FAPI_BASELINE プロファイル
scope に "openid" 含む → OIDC プロファイル
それ以外 → OAuth 2.0 プロファイル
優先順位: FAPI_ADVANCE > FAPI_BASELINE > OIDC > OAuth 2.0
この設計により、同じテナント内で通常のOIDCリクエストとFAPIリクエストを共存できます。scopeに transfers(FAPI Advancedスコープ)を含むリクエストのみがFAPI Advanced検証を受けます。
Step 1: 認可サーバー設定
設定パラメータ一覧
FAPI認定取得に必要な認可サーバー設定パラメータを以下に示します。
プロファイル決定用(extension)
| パラメータ | 説明 | 設定例 |
|---|---|---|
fapi_baseline_scopes | このスコープを含むリクエストをFAPI Baselineとして検証 | ["read", "account"] |
fapi_advance_scopes | このスコープを含むリクエストをFAPI Advancedとして検証 | ["write", "transfers"] |
設定しない場合: FAPIプロファイルが適用されず、通常のOIDC/OAuth 2.0として処理されます。FAPI固有のセキュリティ検証(PKCE S256強制、クライアント認証制限、mTLSバインディング等)は一切行われません。
セキュリティ設定
| パラメータ | 説明 | FAPI要件 | デフォルト |
|---|---|---|---|
tls_client_certificate_bound_access_tokens | アクセストークンにクライアント証明書をバインド | Advanced: 必須 true | false |
require_signed_request_object | Request Object内に全パラメータ(scope含む)を必須化 | Advanced: 推奨 true | false |
pushed_authorization_request_endpoint | PARエンドポイントURL | Advanced (PAR variant): 必要 | "" |
mtls_endpoint_aliases | mTLSエンドポイントのエイリアスマップ | Advanced: 必要 | {} |
authorization_response_iss_parameter_supported | 認可レスポンスにissパラメータを含める (RFC 9207) | 推奨 true | false |
各パラメータの詳細
tls_client_certificate_bound_access_tokens
FAPI 1.0 Advanced Section 5.2.2 clause 5/6:
"shall only issue sender-constrained access tokens"
true の場合:
クライアント証明書 → SHA-256 thumbprint → アクセストークンの cnf クレームに埋め込み
リソースサーバーがトークン使用時に証明書の一致を検証
false の場合:
アクセストークンはベアラートークン(誰でも使用可能)
⚠️ FAPI Advancedリクエスト時にエラー:
"shall only issue sender-constrained access tokens, but server
tls_client_certificate_bound_access_tokens is false"
重要: この 設定はサーバーレベルとクライアントレベルの両方で true が必要です。どちらか一方が false でもFAPI Advancedリクエストはエラーになります。
require_signed_request_object
FAPI 1.0 Advanced Section 5.2.2 clause 13 および RFC 9101 Section 6.3:
"shall require the request object to contain all the authorization request parameters"
true の場合:
Request Object JWT 内に scope クレームが必須
→ scope がJWT外(クエリパラメータ)にあってもJWT内のものだけが使用される
false の場合:
scope は Request Object JWT の外側(クエリパラメータ)でも受け入れられる
⚠️ FAPI Advanced 仕様では全パラメータをRO内に含めることを要求しているため、
false だと仕様に厳密には準拠しないが、検証自体はエラーにならない
注意: false でもFAPI Advancedの他のチェック(署名、aud、nbf/exp等)は通過します。ただしOIDFテストスイートがscopeをRequest Object内に含めて送信するケースが多いため、false でもテストが通る可能性はあります。厳密な仕様準拠のためには true を推奨します。
pushed_authorization_request_endpoint
RFC 9126 に基づくPARエンドポイントのURL。
設定済みの場合:
- PARエンドポイントが利用可能になる
- client_assertion JWTの aud 検証でPARエンドポイントURLも受け入れる
- Discovery応答 (.well-known) にPARエンドポイントが含まれる
未設定(空文字)の場合:
- PARは利用不可
- OIDFテストの pushed variant は実行不可
mtls_endpoint_aliases
RFC 8705 Section 5: mTLSエンドポイントのエイリアスマッピング。
設定済みの場合:
- Discovery応答にmTLSエンドポイントが公開される
- client_assertion JWTの aud 検証でmTLSエイリアスURLも受け入れる
- クライアントはmTLSエンドポイント経由でアクセスできる
未設定の場合:
- mTLSクライアント認証(tls_client_auth)は利用可能だが
mTLSエンドポイント経由のアクセスは不可
- ⚠️ OIDFテストはmTLSエンドポイントを使用するため失敗する
設定例(FAPI Advanced対応)
curl -X PUT "https://api.local.test/v1/management/tenants/{tenant-id}/authorization-server" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"issuer": "https://api.local.test/{tenant-id}",
"authorization_endpoint": "https://api.local.test/{tenant-id}/v1/authorizations",
"token_endpoint": "https://api.local.test/{tenant-id}/v1/tokens",
"userinfo_endpoint": "https://api.local.test/{tenant-id}/v1/userinfo",
"jwks_uri": "https://api.local.test/{tenant-id}/v1/jwks",
"pushed_authorization_request_endpoint": "https://api.local.test/{tenant-id}/v1/authorizations/push",
"mtls_endpoint_aliases": {
"token_endpoint": "https://mtls.api.local.test/{tenant-id}/v1/tokens",
"userinfo_endpoint": "https://mtls.api.local.test/{tenant-id}/v1/userinfo",
"pushed_authorization_request_endpoint": "https://mtls.api.local.test/{tenant-id}/v1/authorizations/push",
"introspection_endpoint": "https://mtls.api.local.test/{tenant-id}/v1/tokens/introspection",
"revocation_endpoint": "https://mtls.api.local.test/{tenant-id}/v1/tokens/revocation"
},
"token_endpoint_auth_methods_supported": [
"private_key_jwt",
"tls_client_auth",
"self_signed_tls_client_auth"
],
"token_endpoint_auth_signing_alg_values_supported": ["ES256", "PS256"],
"response_types_supported": ["code", "code id_token"],
"response_modes_supported": ["query", "fragment", "jwt", "query.jwt", "fragment.jwt"],
"id_token_signing_alg_values_supported": ["ES256", "PS256"],
"request_object_signing_alg_values_supported": ["ES256", "PS256"],
"authorization_signing_alg_values_supported": ["ES256", "PS256"],
"code_challenge_methods_supported": ["S256"],
"tls_client_certificate_bound_access_tokens": true,
"require_signed_request_object": true,
"authorization_response_iss_parameter_supported": true,
"jwks": "{...サーバーの署名鍵(ES256 or PS256)...}",
"extension": {
"access_token_type": "JWT",
"token_signed_key_id": "signing_key",
"id_token_signed_key_id": "signing_key",
"access_token_duration": 300,
"id_token_duration": 300,
"refresh_token_duration": 2592000,
"id_token_strict_mode": true,
"fapi_baseline_scopes": ["read", "account"],
"fapi_advance_scopes": ["write", "transfers"],
"pushed_authorization_request_expires_in": 60,
"authorization_code_valid_duration": 60
}
}'
Step 2: クライアント設定
FAPIクライアントに必要な設定パラメータを示します。
設定パラメータ一覧
| パラメータ | 説明 | FAPI Baseline | FAPI Advanced |
|---|---|---|---|
token_endpoint_auth_method | クライアント認証方式 | mTLS / private_key_jwt / client_secret_jwt | mTLS / private_key_jwt のみ |
tls_client_certificate_bound_access_tokens | mTLSバインドAT | 任意 | 必須 true |
request_object_signing_alg | Request Object署名アルゴリズム | 任意 | ES256 or PS256 |
id_token_signed_response_alg | ID Token署名アルゴリズム | 任意 | ES256 or PS256 推奨 |
authorization_signed_response_alg | JARM署名アルゴリズム | 不要 | ES256 or PS256(JARMモード時) |
redirect_uris | リダイレクトURI | https必須 | https必須 |
response_types | レスポンスタイプ | code | code or code id_token |
クライアント認証方式の選択
FAPI Advancedでは以下の3方式のみ 許可されます:
| 認証方式 | 説明 | 追加設定 |
|---|---|---|
tls_client_auth | CA発行クライアント証明書 | tls_client_auth_subject_dn |
self_signed_tls_client_auth | 自己署名クライアント証明書 | jwks(公開鍵) |
private_key_jwt | JWT Bearer認証 | jwks(公開鍵), token_endpoint_auth_signing_alg |
禁止されるクライアント認証方式:
❌ client_secret_basic → Baseline, Advanced 共に禁止
❌ client_secret_post → Baseline, Advanced 共に禁止
❌ client_secret_jwt → Advanced で追加禁止
❌ none (Public Client) → Advanced で禁止