コンテンツにスキップ

CIBA

CIBA (Client Initiated Backchannel Authentication)

CIBAは、クライアントがユーザーのデバイスに直接アクセスすることなく、ユーザーの認証リクエストを開始できる認証フローです。認証は別のデバイス(例:モバイル電話)でバックチャネルを通じて行われます。

概要

なぜCIBAを使用するのか?

ユースケース

  • IoTデバイス: 入力機能のないデバイスでユーザーを認証
  • コールセンター: エージェントが顧客のモバイルデバイスで認証を開始
  • バンキング: Webアプリケーション使用中にモバイルアプリで取引承認
  • スマートTV: TVリモコンで入力する代わりに電話で認証

Device Flowとの比較

機能CIBADevice Flow
ユーザー識別クライアントがユーザーヒントを提供ユーザーがコードを入力
開始クライアント開始ユーザー開始
ユーザー発見サーバーがユーザーを認識ユーザーが自己識別
最適用途既知のユーザー、バックチャネル不明なユーザー、セルフサービス

CIBAの仕組み

フロー概要

  1. クライアントがリクエストを開始: login_hint付きでPOST /bc-authorizeを送信
  2. サーバーが通知を送信: ユーザーのデバイスに通知(プッシュ、SMS、メール)
  3. ユーザーが承認: ユーザーがデバイスでリクエストを承認
  4. クライアントがトークンをポーリング: クライアントが/tokenエンドポイントをポーリング(pollモード)
  5. サーバーがトークンを返却: ユーザー承認後、トークンを返却

トークン配信モード

クライアントがauth_req_idでトークンエンドポイントをポーリング:

POST /token
grant_type=urn:openid:params:grant-type:ciba
&auth_req_id=1c266114-a1be-4252-8ad1-04986c5b9ac1
&client_id=my_client_id
&client_secret=my_client_secret

APIリファレンス

バックチャネル認証エンドポイント

POST /bc-authorize

リクエスト

POST /bc-authorize HTTP/1.1
Content-Type: application/x-www-form-urlencoded
scope=openid+profile+email
&client_id=my_client_id
&client_secret=my_client_secret
&login_hint=[email protected]
&binding_message=Transaction+ID:+12345

リクエストパラメータ

パラメータ必須説明
scopeYesOAuthスコープ(openidを含む必要がある)
client_idYesクライアント識別子
login_hintいずれか*ユーザー識別子(メール、電話、ユーザー名)
login_hint_tokenいずれか*ログインヒントを含むJWT
id_token_hintいずれか*以前発行されたIDトークン
binding_messageNo人間が読めるメッセージ(最大140文字)
user_codeNoユーザー確認コード
requested_expiryNoリクエスト有効期限(秒)
client_notification_token条件付きping/pushモードで必須

*login_hintlogin_hint_tokenid_token_hintのいずれか1つが必須

レスポンス

{
"auth_req_id": "1c266114-a1be-4252-8ad1-04986c5b9ac1",
"expires_in": 300,
"interval": 5
}

トークンエンドポイント(Pollモード)

POST /token

POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
grant_type=urn:openid:params:grant-type:ciba
&client_id=my_client_id
&client_secret=my_client_secret
&auth_req_id=1c266114-a1be-4252-8ad1-04986c5b9ac1

レスポンス状態

保留中:

{
"error": "authorization_pending",
"error_description": "ユーザーはまだ認証リクエストを認可していません"
}

拒否:

{
"error": "access_denied",
"error_description": "ユーザーが認証リクエストを拒否しました"
}

成功:

{
"access_token": "eyJhbGc...",
"token_type": "Bearer",
"expires_in": 3600,
"id_token": "eyJhbGc...",
"refresh_token": "eyJhbGc...",
"scope": "openid profile email"
}

ログインヒント形式

login_hintパラメータは複数の形式をサポート:

メール

電話(E.164)

login_hint=+14155552671
login_hint=tel:+14155552671

サブジェクト識別子

login_hint=sub:user123

ユーザー名

login_hint=johndoe

バインディングメッセージ

binding_messageは承認時にユーザーに表示されます:

binding_message=Banking Appにサインイン
binding_message=取引ID: 12345
binding_message=$100.00の支払いを承認

制約:

  • 最大140文字
  • Unicode文字、数字、句読点、スペースを許可
  • ユーザー承認UIで目立つように表示

使用例

// 1. CIBAリクエストを開始
const cibaResponse = await fetch('https://auth.example.com/bc-authorize', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
scope: 'openid profile email',
client_id: 'my_client_id',
client_secret: 'my_client_secret',
login_hint: '[email protected]',
binding_message: 'My Appにサインイン',
}),
});
const { auth_req_id, interval } = await cibaResponse.json();
// 2. トークンをポーリング
let tokens;
while (!tokens) {
await new Promise(resolve => setTimeout(resolve, interval * 1000));
const tokenResponse = await fetch('https://auth.example.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'urn:openid:params:grant-type:ciba',
client_id: 'my_client_id',
client_secret: 'my_client_secret',
auth_req_id,
}),
});
if (tokenResponse.ok) {
tokens = await tokenResponse.json();
}
}
console.log('認証完了:', tokens);

セキュリティ考慮事項

ログインヒント検証

  • ログインヒントが正しい形式であることを検証
  • 通知開始前にユーザーが存在することを確認
  • スパム防止のためログインヒントごとにレート制限

バインディングメッセージインジェクション

  • フィッシング防止のためバインディングメッセージをサニタイズ
  • 生テキストのみ表示、HTMLやスクリプトなし
  • UI問題防止のため長さを制限

リプレイ保護

  • auth_req_idは1回限りの使用
  • リクエストは設定されたタイムアウト後に期限切れ(デフォルト5分)
  • トークン発行はアトミックで追跡

クライアント認証

  • CIBAでは常にクライアント認証を要求
  • client_secretまたは相互TLSを使用
  • クライアントがCIBAグラントタイプを認可されていることを検証

エラーコード

エラーHTTPステータス説明
invalid_request400必須パラメータの欠落または無効な形式
unauthorized_client401クライアントがCIBA用に登録されていない
expired_token400承認前に認証リクエストが期限切れ
authorization_pending400ユーザーがまだ承認していない
slow_down400クライアントのポーリングが頻繁すぎる
access_denied403ユーザーがリクエストを拒否

参考資料