Skip to content

CIBA — Client-Initiated Backchannel Authentication ​

CIBA は Device Code とは別の形の問題を解きます。device code は 2 つの面が「画面に表示された短いコード」を介して OP で合流します。CIBA ではリクエストを開始する装置がそもそも ユーザに見えていない — 組み込み側の通知サービスが、ユーザがすでに信頼している 別の認証デバイス に要求を届けます。

代表的な構成:

  • 利用デバイス(consumption device) — POS 端末、コールセンタの操作画面、店内のキオスク端末、銀行の振込承認パネル等。誰 であるべきかは知っている(ロイヤリティカード、電話番号、口座番号)が、認証する手段はない。
  • 認証デバイス(authentication device) — ユーザのスマホで、銀行アプリがすでにインストール・サインイン済み。組み込み側の通知サービスが「Acme Coffee で 800 円を承認しますか?」などの要求を表示し、ユーザは 承認 / 拒否 をタップする。

利用デバイスはユーザに credential を一切聞きません — OP に「Alice にスマホで承認してもらってください」と頼むだけです。

このページで触れる仕様
用語の補足
  • auth_req_id — /bc-authorize の応答として返る不透明な識別子。利用デバイスはこれを使って /token をポーリングし、認証デバイスはこれに対して承認する。
  • Hint — 利用デバイスが OP に どのユーザ を聞くかを伝える方法。CIBA Core §7.1 で 3 種類が定義されている:
    • login_hint — 組み込み側が subject にマップする不透明値([email protected]、口座番号など)。
    • id_token_hint — 過去に発行された ID トークン。sub claim でユーザを識別する。
    • login_hint_token — 組み込み側が署名検証してから subject にマップする署名付き JWT(別の上流システムが発行したものなど)。
  • 配信モード — OP が承認を利用デバイスに伝える方法:
    • poll — デバイスが auth_req_id で /token をポーリングします。本ライブラリが実装している配信モードはこれだけです。

フローの動き方(poll モード) ​

OP がスマホに働きかけ、端末はポーリングするだけ
CIBA の poll モードを示した図。POS 端末が backchannel authentication エンドポイントを呼び、OP が login hint を subject に解決し、組み込み側の通知サービスがスタッフのスマホへ届け、端末はユーザが承認するまでトークンエンドポイントをポーリングします。要求を開始する承認を待つPOS 端末利用デバイスOPgo-oidc-providerスタッフのスマホ認証デバイスPOST /bc-authorizelogin_hint · binding_messagehint を subject に解決HintResolver → subject通知サービスAcme Coffee: 800 円を承認?200 · auth_req_idexpires_in: 600 · interval: 5POST /token · ポーリングgrant_type=…:ciba400 · authorization_pendingユーザがスマホ上で承認approve(auth_req_id)POST /token · 次のポーリング200 · access_tokenid_token · refresh_token?
端末とスマホは互いに通信しません。両者が触れるのは OP だけです。binding_message が重要なのはそのためで、端末の前にいる人とスマホを持つ人が突き合わせられる唯一の文字列がこれです。

利用デバイスはユーザの credential を持ちません。ユーザは利用デバイスに何も打ちません。認証デバイス — ユーザが銀行アプリにサインイン済みなのですでに認証されている — だけが consent を行使する場所になります。

CIBA と Device Code — どちらを選ぶか ​

両方とも 2 デバイスです。違いは 「利用デバイスが聞いていることをユーザが知っているか」 です。

Device CodeCIBA
誰が信頼を起こす?ユーザが認証ページに user_code を打ち込む利用デバイスが OP に要求し、組み込み側の認証デバイスサービスが表示する
ユーザは URL を発見する必要がある?はい — verification_uri が画面に出るいいえ — 配備側が認証デバイスをあらかじめ把握している
利用デバイス側の信頼モデル匿名のデバイスがユーザに「結びつけて」とお願いする事前登録されたデバイスが、OP 経由でユーザに「確認して」とお願いする
代表的な利用面スマート TV、ゲーム機、CLI、IoT 機器のペアリングPOS、コールセンタ、不正検知の確認、アプリ内決済
ユーザが打つ識別子user_code(BDWP-HQPK 等)なし — OP はすでにユーザ識別子を持っている(login_hint)
誤誘導のリスク低 — URL がデバイス画面に出ている中 — 別経路の通知文言が利用面と一致しているとユーザが信頼する必要がある。binding_message を使ってスマホ側プロンプトに POS の要求内容を表示すること

ユーザが デバイスの目の前にいて デバイスがコード表示できないなら CIBA。ユーザが デバイスから離れていて デバイスが画面を持っているなら device code。CIBA の認証デバイスは事前にユーザを知っている必要があり、device code の verification ページは任意のサインイン済みブラウザセッションで動きます。

Hint — 「どのユーザか」を OP に伝える ​

利用デバイスはユーザを認証できないので、OP に どのユーザを承認サービスの対象にするか を伝える必要があります。CIBA Core §7.1 は 3 種類の hint を定義しており、OP は単一の HintResolver インタフェースでそれら全てを受け付けます:

go
op.WithCIBAGrant(op.CIBAGrant{
    HintResolver: op.HintResolverFunc(
        func(ctx context.Context, kind op.HintKind, value string) (string, error) {
            switch kind {
            case op.HintLoginHint:
                // value = "alice"、"[email protected]"、口座番号など。
                return resolveLoginHint(ctx, value)
            case op.HintIDTokenHint:
                // value は raw JWT ではなく、OP が検証した subject です。
                // OP は署名、issuer、認証済みクライアントの audience を検証しますが、
                // CIBA hint では exp を意図的に検証しません。
                return lookupSubject(ctx, value)
            case op.HintLoginHintToken:
                // value = 信頼している別システムが発行した署名付き JWT。
                return verifyAndMap(ctx, value)
            }
            return "", op.ErrUnknownCIBAUser
        },
    ),
})

op.ErrUnknownCIBAUser を返すと、通信路上の応答は unknown_user_id に丸められます。それ以外のエラーは login_required になります。op.WithCIBAGrant を HintResolver 未指定で呼ぶと op.New は構築に失敗します — リゾルバは必須です。

HintIDTokenHint では、OP が自分の鍵、issuer、認証済みクライアントの audience に対して JWT を検証し、検証済みの sub だけを Resolve に渡します。exp は意図的に検証しません。typ ヘッダが無い、または JWT 以外のトークンは拒否するので、logout token やアクセストークンを hint として通すことはできません。pairwise subject を登録したクライアントは、sector ごとの sub を元の subject に戻せないため Resolve の前に拒否されます。そのクライアントは login_hint または login_hint_token を使ってください。resolver で raw JWT を parse してはなりません。

binding_message — 誤誘導を防ぐ項目 ​

CIBA の binding_message は利用デバイスが /bc-authorize 時に送れる短い文字列です。OP はこれを認証デバイスに転送し、ユーザのスマホ側プロンプトにレジ係が POS で見ているのと同じ文言を表示できます:

Acme POS 端末 #14: Acme Coffee で 800 円を承認しますか?

[ 承認 ] [ 拒否 ]

binding_message がないと、ユーザは OP の汎用プロンプトしか頼りになりません。「異常なアクティビティを検知しました。この通知を承認してください」のような phishing がはるかに通りやすくなります。仕様上は optional ですが、組み込み側の UX では 必須 として扱ってください。

OP が受け付けるのは 50 文字までで、制御文字は拒否します(400 invalid_binding_message)。文字列は受け取ったとおりに転送し、HTML エスケープはしません。両方のデバイスで同じ文言を表示できるようにするためです。表示先に合わせたエスケープは組み込み側で行ってください。

各エンドポイントの応答 ​

/bc-authorize はリクエストの時点で次のように拒否します。

条件応答
hint が解決できない(op.ErrUnknownCIBAUser)400 unknown_user_id
リゾルバがそれ以外のエラーを返したlogin_required
pairwise クライアントからの id_token_hint400 invalid_request
binding_message が長すぎる、または制御文字を含む400 invalid_binding_message
user_code または client_notification_token が付いている400 invalid_request(どちらも未対応)
requested_expiry が正の整数でない、または profile.FAPICIBA 下で 10 分を超える400 invalid_request(FAPI-CIBA 以外で CIBAGrant.MaxRequestTTL を超える値は切り詰められる)
クライアントの JWKS を取得できない request object503

grant_type=urn:openid:params:grant-type:ciba の /token は、Device Code と同じ 4 つのポーリング用コードで応答します。authorization_pending、slow_down、access_denied(認証デバイスで拒否された、または slow_down 違反が 5 回)、expired_token です。

auth_req_id の有効期間は既定で 600 秒(requested_expiry で短縮可能)、interval は 5 秒です。op.CIBAGrant の DefaultRequestTTL、MaxRequestTTL、PollInterval フィールドで調整できます。負の値、および profile.FAPICIBA 下での 10 分を超える有効期間は、op.New が失敗します。

承認されたリクエストを引き換える時点で、OP は Device Code と同様にそのクライアントへの同意の grant を記録します。introspection と /userinfo は公開(pairwise)subject を返し、subject の失効でトークンも失効し、同じ scope での後続の /auth では同意画面が省略されます。

動かしてみる ​

examples/32-ciba-pos は完全な POS シナリオを実演します。POS が /bc-authorize に POST、スタッフのスマホ(CIBARequestStore.Approve を直接呼ぶ goroutine でシミュレート)が承認、POS がトークン発行までポーリングします。end-to-end で 5 秒程度です。

sh
(cd examples/32-ciba-pos && GOWORK=off go run -tags example .)

example はロール別ファイルに分割されています(op.go で OP の組み立て + HintResolver、rp.go で POS 側のポーリング、device.go でスマホ承認のシミュレーション)。

続きはこちら ​

  • ユースケース: CIBA の組み込み — op.WithCIBAGrant、HintResolver の契約、FAPI-CIBA プロファイル制約、組み込み側の認証デバイスコールバックが CIBARequestStore.Approve に応答する手順。
  • 認可コード + PKCE — ユーザがクライアントの目の前にいるときに使うフロー。
  • Device Code 入門 — 「ユーザが別の利用面にいる」という同系統の概念。コード表示を使う方式。