跳到內容

Client Initiated Backchannel Authentication(CIBA)

Client Initiated Backchannel Authentication(CIBA) 是 OpenID Connect 的擴展規範,定義了一種不依賴瀏覽器重導的身分驗證流程。

傳統的 OpenID Connect 流程都依賴瀏覽器重導——使用者在同一台裝置上被導向 OP 登入,再導回 RP。這在很多場景下行不通:

  • 銀行櫃檯——行員在自己的電腦操作,需要客戶在手機上授權
  • 客服中心——客服需要驗證來電者身分,但來電者不在電腦前
  • POS 結帳——收銀台的系統需要顧客用手機授權付款
  • 受限裝置——租借腳踏車站、零售 Kiosk 等無法開瀏覽器的裝置

這些場景的共通點是:發起請求的裝置和使用者進行身分驗證的裝置不是同一台。CIBA 的解法是讓 RP 透過 back-channel 直接與 OP 通訊,OP 再通知使用者在另一台裝置(通常是手機)上完成驗證。

Device Authorization Grant 也解決「跨裝置授權」的問題,但兩者的設計目標不同:

Device Authorization GrantCIBA
使用者識別不需要——使用者自行輸入 user code需要——RP 必須提供使用者的識別資訊
通訊方向裝置輪詢 AS,使用者主動造訪授權頁面RP 直接通知 OP,OP 主動推送給使用者
典型場景Smart TV、遊戲主機(使用者在裝置前)銀行櫃檯、客服中心(使用者不在發起裝置前)
Token 取得只有輪詢Poll、Ping、Push 三種模式

簡單來說:Device Authorization Grant 是「使用者在裝置前,但裝置輸入不方便」;CIBA 是「使用者可能根本不在發起請求的裝置前」。

CIBA 引入了兩個裝置的區分:

裝置角色範例
Consumption Device使用者與 RP 互動的裝置銀行行員的電腦、POS 機、Kiosk
Authentication Device使用者進行身分驗證的裝置使用者的手機

RP 在 Consumption Device 上發起請求,使用者在 Authentication Device 上完成驗證——兩者之間的關聯由 OP 負責串接。

sequenceDiagram
    participant RP as Relying Party<br>(Consumption Device)
    participant OP as OpenID Provider
    participant User as 使用者<br>(Authentication Device)

    RP->>OP: 1. Backchannel Authentication Request
    OP->>RP: 2. 回傳 auth_req_id

    OP->>User: 3. 推送驗證通知
    User->>OP: 4. 使用者完成驗證並授權

    alt Poll 模式
        loop 輪詢
            RP->>OP: 5a. Token Request(帶 auth_req_id)
            OP-->>RP: authorization_pending
        end
        OP->>RP: 核發 Token
    else Ping 模式
        OP->>RP: 5b. 通知 RP(帶 auth_req_id)
        RP->>OP: Token Request
        OP->>RP: 核發 Token
    else Push 模式
        OP->>RP: 5c. 直接推送 Token
    end

Step 1:Backchannel Authentication Request

Section titled “Step 1:Backchannel Authentication Request”

RP 向 OP 的 Backchannel Authentication Endpoint 發送請求:

POST /bc-authorize HTTP/1.1
Host: op.example.com
Content-Type: application/x-www-form-urlencoded
scope=openid%20profile
&login_hint=[email protected]
&binding_message=ABCD1234
&client_notification_token=8d67dc78-7faa-4d41-aabd-67707b374255
參數必要性說明
scopeREQUIRED必須包含 openid
login_hint三擇一使用者的識別資訊(如 email、電話號碼)
id_token_hint三擇一先前核發的 ID Token,用於識別使用者
login_hint_token三擇一已簽署的 Token,包含使用者識別資訊
binding_messageOPTIONAL顯示在兩台裝置上的關聯訊息(見下方說明)
user_codeOPTIONAL使用者的 PIN 或密碼,防止未經請求的通知
client_notification_tokenPing/Push 必要OP 回呼 RP 時使用的 Bearer Token(至少 128 bits 熵)
acr_valuesOPTIONAL偏好的身分驗證等級
requested_expiryOPTIONAL希望 auth_req_id 的有效期(秒)

RP 必須提供 login_hintid_token_hintlogin_hint_token 其中一個(且只能一個),讓 OP 知道要驗證的是哪位使用者。

OP 確認請求有效後,回傳確認回應:

{
"auth_req_id": "1c266114-a1be-4252-8ad1-04986c5b9ac1",
"expires_in": 120,
"interval": 5
}
欄位必要性說明
auth_req_idREQUIRED這次驗證請求的唯一識別碼(至少 128 bits 熵)
expires_inREQUIREDauth_req_id 的有效期(秒)
intervalOPTIONALPoll 模式下的最小輪詢間隔,預設 5 秒

OP 透過自己的機制(推播通知、SMS 等)通知使用者的 Authentication Device。使用者在手機上看到驗證請求,確認後完成身分驗證與授權。

如果 RP 有提供 binding_message,使用者的手機上會顯示這段訊息(例如 ABCD1234),使用者可以對照 Consumption Device 上顯示的同一組訊息,確認兩邊是同一筆交易。

根據 RP 註冊時選擇的模式,有三種方式取得 Token:

RP 定期向 Token Endpoint 輪詢:

POST /token HTTP/1.1
Host: op.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn:openid:params:grant-type:ciba
&auth_req_id=1c266114-a1be-4252-8ad1-04986c5b9ac1

使用者尚未完成時回傳 authorization_pending,輪詢太頻繁回傳 slow_down(與 Device Authorization Grant 相同的錯誤碼)。

OP 在使用者完成後,向 RP 註冊的 backchannel_client_notification_endpoint 發送通知:

POST /ciba-notification HTTP/1.1
Host: rp.example.com
Authorization: Bearer 8d67dc78-7faa-4d41-aabd-67707b374255
Content-Type: application/json
{
"auth_req_id": "1c266114-a1be-4252-8ad1-04986c5b9ac1"
}

RP 收到通知後再向 Token Endpoint 請求 Token。

OP 直接將 Token 推送到 RP 的通知端點:

POST /ciba-notification HTTP/1.1
Host: rp.example.com
Authorization: Bearer 8d67dc78-7faa-4d41-aabd-67707b374255
Content-Type: application/json
{
"auth_req_id": "1c266114-a1be-4252-8ad1-04986c5b9ac1",
"access_token": "eyJhbGciOiJSUzI1NiJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"id_token": "eyJhbGciOiJSUzI1NiJ9..."
}

Push 模式下,ID Token 必須包含額外的 hash 值(at_hashurn:openid:params:jwt:claim:auth_req_id)來防止竄改。

PollPingPush
RP 需要公開端點不需要需要需要
Token 取得方式RP 輪詢 Token EndpointOP 通知 → RP 再取 TokenOP 直接推送 Token
實作複雜度
即時性取決於輪詢間隔最高
client_notification_token不需要需要需要

binding_message 是讓使用者確認「兩台裝置上看到的是同一筆交易」的機制。但規範要求它必須簡短且使用有限的純文字字元,因為它要在各種裝置上顯示(手機推播、SMS 等)。這代表它能攜帶的資訊有限,無法完整描述交易內容。

user_code 可以防止使用者收到未經請求的驗證通知——只有知道使用者 PIN 的 RP 才能發起請求。但這代表使用者每次都要輸入 PIN,增加了操作步驟。並非所有 OP 都支援此參數。

Push 模式最即時,但也最複雜:RP 必須驗證 ID Token 中的 hash 值、確保通知端點的安全、處理 Token 被攔截的風險。規範建議 Push 模式應使用 sender-constrained access token 來降低 Token 被攔截後濫用的風險。

如果使用 login_hint_token 來識別使用者,規範要求它必須經過數位簽署,以防止攻擊者注入偽造的識別資訊、冒充其他使用者發起驗證。

OP 應確認 RP 註冊的 backchannel_client_notification_endpoint 確實屬於該 RP 的管理範圍,避免 Token 被送到錯誤的接收端。

沒有 user_code 機制時,任何知道使用者識別資訊(如 email)的 RP 都能觸發驗證通知推送到使用者的手機上。這可能被濫用為騷擾手段,或透過疲勞攻擊(notification fatigue)誘騙使用者不小心同意授權。user_code 是主要的防禦措施。

Push 模式下,Token 透過網路直接傳送到 RP 的端點,有被中間人攔截或竄改的風險。規範要求 ID Token 必須包含 at_hash(Access Token hash)與 urn:openid:params:jwt:claim:auth_req_id(請求 ID),讓 RP 能驗證 Token 的完整性。