بنقرة واحدة
spec-fapi
FAPI(Financial-grade API)機能の開発・修正を行う際に使用。FAPI 1.0 Baseline/Advanced, FAPI CIBA, mTLS, PAR, JARM実装時に役立つ。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
FAPI(Financial-grade API)機能の開発・修正を行う際に使用。FAPI 1.0 Baseline/Advanced, FAPI CIBA, mTLS, PAR, JARM実装時に役立つ。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
UserInfoエンドポイント(UserInfo Endpoint)機能の開発・修正を行う際に使用。UserInfo claims、scopeフィルタリング、verified_claims実装時に役立つ。
外部API認証ユースケースの設定ガイド。外部API連携(認証委譲、リスク判定、OTP等)の interaction 設計、identity_match_field、MFA 2段階目、previous_interaction のヒアリングと設定JSONを提供。
ユースケース別セットアップのエントリポイント。ユーザーにユースケースを選択してもらい、対応するスキル(use-case-login, use-case-mfa等)にルーティングする。共通ワークフロー、前提条件、組み合わせパターンの概要を提供。
認証機能(Authentication Policy, MFA)の開発・修正を行う際に使用。認証ポリシー、パスワード、OTP、FIDO2、条件付き認証実装時に役立つ。
セキュリティ・脆弱性対策の開発・テストを行う際に使用。OAuth/OIDC攻撃対策、認証識別子切り替え攻撃、Session Fixation、マルチテナント分離、セキュリティテスト実装時に役立つ。
外部サービス連携(External Service Integration)機能の開発・修正を行う際に使用。HTTP Request Executor, MappingRule, OAuth/HMAC認証実装時に役立つ。
| name | spec-fapi |
| description | FAPI(Financial-grade API)機能の開発・修正を行う際に使用。FAPI 1.0 Baseline/Advanced, FAPI CIBA, mTLS, PAR, JARM実装時に役立つ。 |
documentation/docs/content_06_developer-guide/04-implementation-guides/oauth-oidc/fapi.md - FAPI実装ガイドdocumentation/docs/content_03_concepts/03-authentication-authorization/concept-06-fapi.md - FAPI概念documentation/docs/content_06_developer-guide/03-application-plane/02-01-authorization-request-verification.md - 認可リクエスト検証フロー詳細(プロファイル決定、検証チェーン、エラーハンドリング)documentation/requirements/fapi-1.0-gap-analysis.yaml - FAPI 1.0 Gap分析(OIDF適合性テスト結果と修正記録)documentation/docs/content_05_how-to/phase-2-security/05-fapi-setup.md - FAPIセットアップガイド(プロファイル決定、認可サーバー/クライアント設定、OIDF認定チェックリスト)documentation/requirements/fapi-1.0-advanced-op-test-mapping.md - FAPI 1.0 Advanced OPテスト63件とRFC/仕様要件のマッピング表FAPIは、金融グレードのセキュリティを実現するOIDC/OAuth 2.0プロファイル。
FAPIプロファイルはリクエストのスコープとテナントのextension設定で自動決定される。
| 優先度 | 条件 | プロファイル |
|---|---|---|
| 1 | テナントextension.fapi_advance_scopesに該当するスコープあり | FAPI_ADVANCE |
| 2 | テナントextension.fapi_baseline_scopesに該当するスコープあり | FAPI_BASELINE |
| 3 | openidスコープを含む | OIDC |
| 4 | 上記以外 | OAUTH2 |
CIBAフローではbaseline/advanceどちらのスコープでも FAPI_CIBA になる。
詳細: content_06_developer-guide/03-application-plane/02-01-authorization-request-verification.md セクション2.3〜3(プロファイル決定、検証チェーン、エラーハンドリング)
libs/
├── idp-server-core-extension-fapi/ # FAPI拡張モジュール
│ └── .../extension/fapi/
│ ├── FapiBaselineVerifier.java # FAPI Baseline検証
│ ├── FapiAdvanceVerifier.java # FAPI Advanced検証
│ ├── FapiProfileValidator.java # FAPIプロファイル検証
│ ├── TlsClientAuthAuthenticator.java # mTLSクライアント認証
│ └── SelfSignedTlsClientAuthAuthenticator.java
│
├── idp-server-core-extension-fapi-ciba/ # FAPI-CIBA拡張
│ └── .../extension/fapi/ciba/
│ └── FapiCibaVerifier.java
│
├── idp-server-core/ # コア(PAR, JARM実装)
│ └── .../oauth/
│ ├── request/
│ │ └── OAuthPushedRequestParameters.java # PAR
│ ├── response/
│ │ └── JarmCreatable.java # JARM
│ ├── io/
│ │ ├── OAuthPushedRequest.java
│ │ └── OAuthPushedRequestResponse.java
│ └── verifier/extension/
│ └── JarmVerifier.java
│
└── idp-server-control-plane/ # 管理API
└── .../management/fapi/
└── FapiConfigManagementApi.java
idp-server-core-extension-fapi/ モジュール内:
public class FapiBaselineVerifier {
public void verify(
AuthorizationRequest request,
Client client
) {
// 1. response_type=code only
if (!request.responseType().isCode()) {
throw new InvalidRequestException(
"fapi_baseline_requires_code_flow"
);
}
// 2. PKCE必須(S256のみ)
if (!request.hasCodeChallenge()) {
throw new InvalidRequestException(
"code_challenge_required"
);
}
if (request.codeChallengeMethod() != CodeChallengeMethod.S256) {
throw new InvalidRequestException(
"code_challenge_method_must_be_s256"
);
}
// 3. state必須
if (!request.hasState()) {
throw new InvalidRequestException("state_required");
}
// 4. nonce必須(OpenID Connect時)
if (request.scope().contains("openid") &&
!request.hasNonce()) {
throw new InvalidRequestException("nonce_required");
}
}
}
public class FapiAdvanceVerifier {
public void verify(
AuthorizationRequest request,
Client client
) {
// Baseline要件チェック
fapiBaselineVerifier.verify(request, client);
// 1. PAR必須
if (!request.isPushedAuthorizationRequest()) {
throw new InvalidRequestException(
"par_required_for_fapi_advanced"
);
}
// 2. JARM必須
if (!request.hasResponseMode() ||
!request.responseMode().isJwt()) {
throw new InvalidRequestException(
"jarm_required_for_fapi_advanced"
);
}
// 3. mTLS必須
if (!request.hasMtlsCertificate()) {
throw new InvalidRequestException(
"mtls_required_for_fapi_advanced"
);
}
}
}
idp-server-core/oauth/request/ および oauth/io/ 内:
PAR実装は以下のクラスで構成:
OAuthPushedRequestParameters - PAR処理OAuthPushedRequest - リクエスト表現OAuthPushedRequestResponse - レスポンス表現RFC 9126 Section 2.2 に従い、PAR成功レスポンスは HTTP 201 Created を返す。
OAuthPushedRequestStatus.CREATED(201) - 成功ステータスOAuthV1Api のPARエンドポイントは response.statusCode() でステータスを動的に決定FAPI Advanced では認可リクエストに JWS 署名付き Request Object が必須(Section 5.2.2 clause 1)。 PAR 経由のリクエストでは、以下の2段階で検証が分離される:
1. PARエンドポイント(OAuthRequestHandler.handlePushedRequest)
OAuthRequestPattern が NORMAL または REQUEST_OBJECT として解析されるOAuthRequestVerifier.verify() で FAPI Advanced の全検証を実行(署名、exp、nbf、aud 含む)AuthorizationRequest をリポジトリに保存request_uri(urn:ietf:params:oauth:request_uri:...)を発行2. 認可エンドポイント(OAuthRequestHandler.handleRequest)
client_id + request_uri で認可エンドポイントにアクセスOAuthRequestPattern が PUSHED_REQUEST_URI として解析されるPushedRequestUriPatternContextCreator が保存済みパラメータを復元FapiAdvanceVerifier は PAR 経由の場合、以下の検証をスキップ:
isUnsignedRequestObject)PARエンドポイント 認可エンドポイント
┌─────────────────────┐ ┌─────────────────────┐
│ パラメータ受信 │ │ request_uri 受信 │
│ ↓ │ │ ↓ │
│ パターン解析 │ │ PUSHED_REQUEST_URI │
│ (NORMAL/REQUEST_OBJ) │ │ ↓ │
│ ↓ │ │ 保存済みパラメータ復元 │
│ FAPI Advanced 全検証 │ │ (JoseContext は空) │
│ (署名,exp,nbf,aud) │ │ ↓ │
│ ↓ │ │ FAPI Advanced 検証 │
│ クライアント認証 │ │ (JWT検証はスキップ) │
│ ↓ │ │ ↓ │
│ AuthzRequest 保存 │ │ 認可処理続行 │
│ ↓ │ └─────────────────────┘
│ request_uri 発行 │
└─────────────────────┘
関連ファイル:
FapiAdvanceVerifier.java - PAR判定とスキップロジックOAuthRequestHandler.java - PAR/認可の2段階ハンドリングPushedRequestUriPatternContextCreator.java - PAR復元時の空JoseContext生成OAuthRequestPattern.java - NORMAL / REQUEST_OBJECT / REQUEST_URI / PUSHED_REQUEST_URI の4パターンOAuthPushedRequestStatus.java - CREATED(201) / BAD_REQUEST(400) / UNAUTHORIZED(401) / SERVER_ERROR(500)idp-server-core/oauth/response/ 内:
JARM実装は以下のクラスで構成:
JarmCreatable - JARM生成インターフェースJarmVerifier - JARM検証idp-server-core-extension-fapi/ 内:
mTLS実装は以下のクラスで構成:
TlsClientAuthAuthenticator - tls_client_auth方式SelfSignedTlsClientAuthAuthenticator - self_signed_tls_client_auth方式FAPI Advanced準拠に必要な認可サーバー設定:
| 設定 | 値 | 説明 |
|---|---|---|
tls_client_certificate_bound_access_tokens | true | ATをクライアント証明書にバインド |
require_signed_request_object | true | 署名付きリクエストオブジェクト必須 |
pushed_authorization_request_endpoint | 設定必須 | PAR エンドポイント |
POST /v1/authorizations/push にリクエストパラメータを送信request_uri(urn:ietf:params:oauth:request_uri:...)を返却request_uri を使って認可リクエストを送信認可レスポンスをJWTで署名して返す。対応するresponse_mode:
| response_mode | 説明 |
|---|---|
jwt | デフォルトの応答方法をJWTで返す |
query.jwt | クエリパラメータでJWTを返す |
fragment.jwt | フラグメントでJWTを返す |
Discoveryの mtls_endpoint_aliases でmTLS用のエンドポイントURLを公開。クライアント証明書が必要なエンドポイント(トークン、Introspection等)の別URLを提供する。
FAPI Advancedでは private_key_jwt または tls_client_auth を使用。client_secret ベースの認証は非推奨。mTLS環境ではトークンリクエスト時にクライアント証明書のみで認証し、client_secret は不要。
e2e/src/tests/
├── spec/
│ ├── fapi_baseline.test.js # FAPI Baseline仕様
│ ├── fapi_advance.test.js # FAPI Advanced仕様
│ ├── fapi_ciba.test.js # FAPI CIBA仕様
│ ├── rfc9126_par.test.js # PAR (RFC 9126)
│ └── jarm.test.js # JARM仕様
│
├── usecase/financial-grade/
│ ├── financial-grade-01-transfer-flow.test.js
│ └── financial-grade-02-authentication-device-rule.test.js
│
└── security/
└── (FAPI関連セキュリティテスト)
# ビルド
./gradlew :libs:idp-server-core-extension-fapi:compileJava
./gradlew :libs:idp-server-core-extension-fapi-ciba:compileJava
# テスト
cd e2e && npm test -- spec/fapi_baseline.test.js
cd e2e && npm test -- spec/fapi_advance.test.js
cd e2e && npm test -- spec/rfc9126_par.test.js
cd e2e && npm test -- usecase/financial-grade/
OpenID Foundation (OIDF) が提供する適合性テストスイートで、FAPI仕様への準拠を自動検証する。
テストスイートURL: https://www.certification.openid.net/
本プロジェクトでは以下の2つのテストプランを実行:
| テストプラン | 内容 | テスト数 |
|---|---|---|
FAPI 1.0 Advanced Final (fapi1-advanced-final-test-plan) | 認可フロー、Request Object検証、JARM、mTLS、エラーハンドリング | ~30テスト |
FAPI-CIBA ID1 (fapi-ciba-id1-test-plan) | CIBAフロー、poll/pingモード、Request Object検証、Refresh Token | ~30テスト |
OIDF Conformance Suite (https://www.certification.openid.net/)
↕ HTTPS
ローカル idp-server (api.local.test / mtls.api.local.test)
↕
Financial-grade テナント (tenant_id: c3d4e5f6-a7b8-c9d0-e1f2-a3b4c5d6e7f8)
OIDFテストスイートがローカルサーバーにHTTPSでアクセスするため、ローカル環境が外部からアクセス可能である必要がある(ngrok等のトンネリングまたはDNS設定)。
# 1. ローカル環境起動
docker compose up -d
# 2. financial-gradeテナント作成(管理APIで組織・テナント・クライアント一括作成)
cd config/examples/financial-grade
./setup.sh
# 3. テナント設定の更新(既存テナントの設定変更時)
./update.sh
# 4. テナント削除(クリーンアップ)
./delete.sh
setup.sh が行うこと:
.envから管理者認証情報を読み込み、アクセストークンを取得onboarding-request.jsonを使って組織+テナント+クライアント群を一括作成主要設定ファイル:
| ファイル | 内容 |
|---|---|
onboarding-request.json | テナント定義 + 全クライアント定義(一括オンボーディング) |
financial-tenant.json | テナント設定のリファレンス(discovery応答に反映される値) |
tls-client-auth-client.json | tls_client_auth方式クライアント |
tls-client-auth-client-2.json | tls_client_auth方式クライアント(2nd client for OIDF) |
private-key-jwt-client.json | private_key_jwt方式クライアント |
financial-client.json | self_signed_tls_client_auth方式クライアント |
authentication-policy/oauth.json | FAPI用認証ポリシー |
certs/ | mTLSクライアント証明書・CA証明書 |
OIDFテストスイートにインポートするJSON設定:
config/examples/financial-grade/oidc-test/
├── fapi/
│ └── tls_client_auth.json # FAPI 1.0 Advanced Final (tls_client_auth)
└── fapi-ciba/
├── tls_client_auth_poll.json # FAPI-CIBA (tls_client_auth + poll)
├── private_key_jwt_poll.json # FAPI-CIBA (private_key_jwt + poll)
└── FAPI-CIBA-test-cases.md # テストケース詳細ドキュメント
設定ファイルの構造:
{
"alias": "テスト計画の識別名",
"server": {
"discoveryUrl": "https://api.local.test/{tenant_id}/.well-known/openid-configuration"
},
"client": { "client_id": "...", "scope": "...", "jwks": {...} },
"client2": { "client_id": "...", "scope": "...", "jwks": {...} },
"mtls": { "key": "...", "cert": "..." },
"mtls2": { "key": "...", "cert": "..." },
"resource": {
"resourceUrl": "https://mtls.api.local.test/{tenant_id}/v1/me/identity-verification/applications"
}
}
注意:
discoveryUrlは通常エンドポイント (api.local.test)resourceUrlはmTLSエンドポイント (mtls.api.local.test) — sender-constrainedトークン検証にクライアント証明書が必要clientとclient2は2クライアントテスト用(証明書バインドアクセストークンの交差検証等)mtls/mtls2はそれぞれのクライアントのTLSクライアント証明書CIBAテストではユーザーがデバイスで認証を承認する必要がある:
# CIBAデバイス認証シミュレーション(テスト中に手動実行)
cd config/examples/financial-grade
./ciba-device-auth.sh
このスクリプトはCIBAバックチャネル認証リクエストに対して、ユーザーの認証承認をシミュレートする。
documentation/requirements/fapi-1.0-gap-analysis.yaml にOIDF適合性テスト結果と修正記録を管理:
code_challenge_method=S256のみ許可(plainは不可)TlsClientAuthAuthenticator の設定を確認responseパラメータのJWT形式を確認discoveryUrlがapi.local.test(通常エンドポイント)を指しているか確認resourceUrlがmtls.api.local.test(mTLSエンドポイント)を指しているか確認host.docker.internal:8445等の旧URL形式が残っていないか確認FAPI Advanced では PAR エンドポイントと認可エンドポイントで検証が分かれる:
request_uri(urn:ietf:params:oauth:request_uri:...)を返却isPushedRequest())は Request Object 署名・JWT クレーム検証をスキップif (!context.isPushedRequest()) {
throwExceptionIfInvalidSigningAlgorithm(context);
// JWT claim validation ...
}
mTLS クライアント認証で SAN (Subject Alternative Name) の4種を検証:
dNSNameuniformResourceIdentifieriPAddressrfc822NameSelfSignedTlsClientAuthAuthenticator は自己署名証明書用(開発/テスト環境向け)。
探索起点: libs/idp-server-core-extension-fapi/