| name | spec-ciba |
| description | CIBA(Client Initiated Backchannel Authentication)機能の開発・修正を行う際に使用。Poll/Push/Pingモード、Login Hint解決、FCM通知実装時に役立つ。 |
CIBA(Client Initiated Backchannel Authentication)開発ガイド
ドキュメント
documentation/docs/content_06_developer-guide/03-application-plane/06-ciba-flow.md - CIBA実装ガイド
documentation/docs/content_03_concepts/03-authentication-authorization/concept-04-authorization.md - 認可概念(CIBA含む)
機能概要
CIBAは、クライアントがバックチャネル経由でユーザー認証を要求するフロー。
- 3つのモード: Poll(ポーリング)、Push(通知)、Ping(通知+ポーリング)
- Login Hint解決: sub:, email:, phone:, device: プレフィックスでユーザー特定
- Binding Message: ユーザーへの確認メッセージ表示
- ID Token Hint: 既存ID Tokenでユーザー特定
- User Code: ユーザー入力コードによる認証
- デバイス通知: FCM push通知
- デバイスシークレット認証: device_secret_jwtによるデバイスエンドポイント認証
デバイスシークレット認証(CIBAフロー)
CIBAフローでモバイルアプリがデバイスエンドポイントにアクセスする際、デバイスシークレットJWTによる認証を要求できます。
設定(テナントポリシー)
{
"identity_policy_config": {
"authentication_device_rule": {
"authentication_type": "device_secret_jwt",
"issue_device_secret": true,
"device_secret_algorithm": "HS256"
}
}
}
フロー
- FIDO-UAF登録時:
device_secretが自動発行される
- CIBAリクエスト:
login_hint=device:{deviceId}でデバイス指定
- デバイスエンドポイントアクセス:
Authorization: Bearer {device_secret_jwt}で認証
- FIDO-UAF認証: 生体認証で本人確認
関連ドキュメント
documentation/docs/content_03_concepts/03-authentication-authorization/concept-10-device-credential.md - デバイスクレデンシャル管理(詳細)
関連E2Eテスト
e2e/src/tests/usecase/device-credential/device-credential-04-device-secret-issuance.test.js - デバイスシークレット発行+CIBA認証
モジュール構成
libs/
├── idp-server-core-extension-ciba/ # CIBA拡張モジュール
│ └── .../core/extension/ciba/
│ ├── handler/
│ │ └── CibaRequestHandler.java # CIBA認証リクエスト処理
│ ├── CibaRequestContext.java # CIBAリクエストコンテキスト
│ ├── grant/
│ │ ├── CibaGrant.java
│ │ ├── CibaGrantFactory.java
│ │ └── CibaGrantService.java # CIBAグラント管理
│ ├── request/
│ │ └── BackchannelAuthenticationRequest.java
│ ├── response/
│ │ └── BackchannelAuthenticationResponse.java
│ └── repository/
│ └── CibaGrantRepository.java
│
├── idp-server-notification-fcm-adapter/ # FCM通知アダプター
│ └── .../notification/fcm/
│ └── FcmNotificationSender.java
│
└── idp-server-control-plane/ # 管理API
└── .../management/ciba/
└── CibaConfigManagementApi.java
CIBA認証リクエスト処理
idp-server-core-extension-ciba/.../core/extension/ciba/handler/CibaRequestHandler.java 内:
CibaRequestHandlerは、BackchannelAuthenticationRequestを処理し、
BackchannelAuthenticationResponseを生成します。
処理フロー(概念的):
- クライアント認証
- Login Hint解決(ユーザー特定)
- auth_req_id生成
- CibaGrant作成・保存
- デバイス通知(FCM)
- BackchannelAuthenticationResponse返却
CIBAグラント管理
idp-server-core-extension-ciba/grant/ 内:
public class CibaGrant {
AuthReqId authReqId;
UserId userId;
ClientId clientId;
Scope scope;
GrantStatus status;
public boolean isAuthenticated() {
return status == GrantStatus.AUTHENTICATED;
}
}
CibaGrantServiceとCibaGrantVerifierが、グラントのライフサイクルを管理します。
FCM通知
idp-server-notification-fcm-adapter/ モジュール内:
FCM (Firebase Cloud Messaging)を使用して、認証デバイスに通知を送信します。
User Code認証
CIBA リクエスト送信元が本当にユーザーの意図を持っているかを追加検証する仕組み。
設定
| 設定 | 場所 | 説明 |
|---|
backchannel_user_code_parameter_supported | 認可サーバー | Discovery に能力を公開 |
required_backchannel_auth_user_code | 認可サーバー extension | 全CIBAリクエストにuser_code必須化 |
backchannel_auth_user_code_type | 認可サーバー extension | 検証タイプ(現在 "password" のみ) |
backchannel_user_code_parameter | クライアント | クライアント単位のopt-in |
実装
UserCodeAsPasswordVerifier がuser_codeの値をユーザーのパスワードハッシュと照合する。user_codeは別のPINではなく、ユーザーのパスワードそのもの。
passwordVerificationDelegation.verify(userCode.value(), user.hashedPassword())
エラーコード:
missing_user_code: required_backchannel_auth_user_code=true だがuser_code未送信
invalid_user_code: user_codeがパスワードと不一致
Login Hint解決
login_hintパラメータのプレフィックスでユーザー特定方法が決まる。
| プレフィックス | 例 | 解決方法 |
|---|
sub: | sub:user-123 | ユーザーIDで検索 |
email: | email:user@example.com | メールアドレスで検索 |
phone: | phone:+819012345678 | 電話番号で検索 |
device: | device:device-uuid | デバイスIDで検索(FIDO-UAFデバイス) |
ex-sub: | ex-sub:external-id | 外部ユーザーIDで検索 |
CIBA固有のトークン・クレーム設定
認可サーバーのトークン設定はCIBAフローにも適用される。
トークン有効期限
{
"access_token_duration": 3600,
"id_token_duration": 3600
}
リフレッシュトークン戦略
| strategy | rotation | 動作 |
|---|
EXTENDS | false | リフレッシュ時に期限延長。同一RTを再利用 |
EXTENDS | true | リフレッシュ時に期限延長。新RT発行、旧RT無効化 |
FIXED | false | 元のRT期限を維持。同一RTを再利用 |
FIXED | true | 元のRT期限を維持。新RT発行、旧RT無効化 |
id_token_strict_mode
id_token_strict_mode: true の場合、ID Tokenから標準クレーム(email, name等)が除外される。CIBAではclaimsパラメータが使用できないため、strict_mode有効時はID Tokenが最小限(sub, iss, aud, exp, iat)になる。UserInfoエンドポイント経由でクレームを取得する設計。
id_token_strict_mode はID Tokenのみに影響し、UserInfoには影響しない。claims:* カスタムクレームもUserInfoからは通常通り返却される。
custom_claims_scope_mapping
custom_claims_scope_mapping: true の場合、claims:* プレフィックス付きスコープ(例: claims:authentication_devices)でカスタムクレームをUserInfo/ID Tokenに含めることができる。false の場合、claims:* スコープは無視される。
id_token_strict_mode との違い: custom_claims_scope_mapping は claims:* カスタムスコープのみに影響し、標準OIDCクレーム(name, email等)には影響しない。一方、id_token_strict_mode は標準クレームをID Tokenから除外するが、UserInfoには影響しない。
claims_supported
認可サーバーの claims_supported に含まれないクレームはUserInfo/ID Tokenから除外される。CIBAでも同様に適用される。
Failure Conditions(認証拒否検出)
CIBAではユーザーがデバイス上で認証を拒否できる。failure_conditions でデバイスレスポンスのどの値を「拒否」と判定するかを設定する。
CibaGrantStatus.isAccessDenied() が条件を評価し、満たされた場合はトークンリクエスト時に access_denied エラーを返す。
E2Eテスト
e2e/src/tests/
├── spec/
│ ├── ciba_authentication_request.test.js # CIBA認証リクエスト
│ ├── ciba_token_request.test.js # CIBAトークンリクエスト
│ ├── ciba_push.test.js # Pushモード
│ ├── ciba_ping.test.js # Pingモード
│ └── ciba_discovery.test.js # CIBA Discovery
│
├── scenario/application/
│ └── scenario-04-ciba-mfa.test.js # CIBA MFAシナリオ
│
├── usecase/ciba/
│ ├── ciba-01-require-rar.test.js # RAR必須
│ ├── ciba-02-multi-device-priority.test.js # マルチデバイス優先度
│ └── ciba-04-security-event-device-ids.test.js
│
└── monkey/
└── ciba-monkey.test.js # CIBAファジングテスト
コマンド
./gradlew :libs:idp-server-core-extension-ciba:compileJava
./gradlew :libs:idp-server-notification-fcm-adapter:compileJava
cd e2e && npm test -- spec/ciba_authentication_request.test.js
cd e2e && npm test -- spec/ciba_push.test.js
cd e2e && npm test -- usecase/ciba/
トラブルシューティング
Login Hint解決失敗
- プレフィックス(sub:, email:, phone:)が正しいか確認
- ユーザーが存在するか確認
Pollモードでauthorization_pending
- ユーザーがまだ認証を完了していない(正常動作)
interval秒待ってから再ポーリング
FCM通知が届かない
- FCMトークンが登録されているか確認
- Firebase設定(credentials.json)が正しいか確認
idp-server-notification-fcm-adapter モジュールが有効か確認
CibaRequestHandler 実装フロー
CibaRequestHandler.handle() は以下の4ステップで処理:
- Validator - 入力形式チェック(
CibaRequestValidator)
- Verifier - ビジネスルール検証
- Context 生成 & 永続化 -
CibaGrant を生成し Repository に保存
- Response 生成 -
auth_req_id を含むレスポンスを返却
探索起点: libs/idp-server-core-extension-ciba/src/main/java/org/idp/server/core/extension/ciba/handler/CibaRequestHandler.java
CibaGrant ライフサイクル
CibaGrant は CibaGrantStatus で状態管理:
authorization_pending → ユーザー認証待ち
authorized → 認証完了(isAuthorized())
access_denied → ユーザー拒否(isAccessDenied())
CibaGrantService は OAuthTokenCreationService を実装し、Token Endpoint での urn:openid:params:grant-type:ciba グラントを処理する。
通知モード実装詳細
| モード | 仕組み | 主要パラメータ |
|---|
| Poll | クライアントが interval 秒ごとにトークンエンドポイントをポーリング | interval(デフォルト5秒) |
| Push | 認証完了時にクライアントの notification_endpoint へ POST | client_notification_token |
| Ping | 認証完了時に簡易通知 → クライアントがトークン取得 | Poll + Push の組み合わせ |