Skip to main content
Agent Identity

OIDF · Final 2021 (errata revisions exist)

OpenID Connect Client-Initiated Backchannel Authentication Flow — Core 1.0

OpenID.CIBA

OIDF FinalStableAuthenticationAgent-specificField guide

OpenID Connect Client-Initiated Backchannel Authentication Flow — Core 1.0 (OpenID.CIBA) is OIDF Final, Final 2021 (errata revisions exist). This is the existing standard for human-in-the-loop approval when the agent is unattended. If a vendor says 'async authorization for genAI', they are often wrapping CIBA.

At a glance

Problem
The client has an identifier for the user but the user is not in a browser in front of that client — they will authenticate and consent on another device (phone, hardware token).
Identity / authn / authz
Authentication and consent, decoupled from the consumption device. The tokens that result are still OAuth/OIDC tokens (authorization).

Actors

  • Consumption device (the agent)
  • Authentication device (user's phone)
  • OpenID provider
  • User

How CIBA works

Animated sequence · CIBA

CIBA — How does an unattended client get approval on another device?

Backchannel grant, not a redirect

Client-Initiated Backchannel Authentication: the client has no browser. It POSTs a backchannel authentication request, gets auth_req_id, and waits. The user is notified, authenticates, and consents on the authentication device. Token delivery is poll by default; ping and push are alternatives named in Why — the wait is not skipped.

Client (agent)sends
OpenID providergets
User (auth device)
Resource server

Now · 1/9· Discover· OpenID CIBAYou are here

Client (agent)→OpenID provider·POSTs a backchannel authentication request: login_hint, scope, binding_message

The client POSTs the backchannel authentication endpoint with a hint for which user, the scope, and a binding_message the user will see.

Why There is no front-channel redirect. The client is unattended. This is not the authorization endpoint used by code+PKCE.

The unattended desk phones the notary instead of sending the owner a browser link.

  • backchannel_authentication_endpoint from the spec
  • login_hint from the spec
  • binding_message from the spec
  • scope from the spec

Solid = from the spec

Step 1 of 9: agent to op. POSTs a backchannel authentication request: login_hint, scope, binding_message OpenID CIBA
Speed
ShareLinkedInX

CIBA authenticates and consents a grant. It does not replace resource-server policy. XAA is a different control for pre-approved app connections. Poll is the default delivery shown; ping and push change who speaks first, not whether the user must finish.

Hop list

Sequence above; this list is the same hops for reading and search. Each row is one message.

  1. 1

    Client (agent)→OpenID providerOpenID CIBAPOSTs a backchannel authentication request: login_hint, scope, binding_message

  2. 2

    OpenID provider→Client (agent)OpenID CIBAReturns auth_req_id (and expires_in, interval)

  3. 3

    OpenID provider→User (auth device)OpenID CIBANotifies the authentication device with the same binding_message

  4. 4

    User (auth device)→OpenID providerOpenID CIBAAuthenticates on the authentication device

  5. 5

    User (auth device)→OpenID providerOpenID CIBAConsents — approves or denies — on the authentication device

  6. 6

    Client (agent)→OpenID providerOpenID CIBAPolls the token endpoint: grant_type CIBA + auth_req_id — authorization_pending

  7. 7

    Client (agent)→OpenID providerOpenID CIBAPolls again after the wait — the user has now consented

  8. 8

    OpenID provider→Client (agent)OpenID CIBADelivers the tokens for that approved action

  9. 9

    Client (agent)→Resource serverRFC 6750Calls the RS with the access token — never with auth_req_id

01

The gap for agents

The client has an identifier for the user but the user is not in a browser in front of that client — they will authenticate and consent on another device. This is the existing standard for human-in-the-loop approval when the agent is unattended. If a vendor says 'async authorization for genAI', they are often wrapping CIBA.

Use CIBA for 'agent wants to do X while the user is away'; XAA for 'IT already authorized this app connection'; AAuth missions for natural-language, multi-resource intent; RFC 9470 when the RS demands stronger auth on an existing grant.

02

Actors and trust boundaries

Consumption device (the agent) never sees the user's password. Authentication device (phone) is where the user actually authenticates. The OP binds them with auth_req_id and an optional binding_message so the user knows which action they are approving. Polling the token endpoint must be authenticated as the client.

03

Mechanics

Client POSTs to the backchannel authorization endpoint with a login hint, scope, optional binding_message and requested_expiry. OP returns auth_req_id. User is notified out of band. Client polls (or uses ping/push) the token endpoint with grant_type=urn:openid:params:grant-type:ciba until approved, denied, or expired. FAPI 2.0 Security Profile supports CIBA and notes that authorization-code and CIBA have been through detailed security analysis.

auth_req_idfrom spec
Quoted: handle for the pending authentication.
binding_messagefrom spec
Quoted: short string shown on both agent UI and phone so the user knows which action they are approving.
grant_type=urn:openid:params:grant-type:cibafrom spec
Quoted token-endpoint grant while polling.

04

Step-by-step flows

Flow 1

Poll until the phone approves

  1. 1

    Agent POSTs backchannel authorize: login_hint, scope, binding_message describing the tool call, client auth.

  2. 2

    OP returns auth_req_id (and expires_in / interval).

  3. 3

    User sees a push with the binding message and approves or denies.

  4. 4

    Agent polls token endpoint with grant_type CIBA + auth_req_id (slow_down / pending / denied / expired).

  5. 5

    On success, ID Token + access token as in OIDC. Use the access token at the API, not the ID Token.

05

Identity vs authentication vs authorization

Authentication and consent, decoupled from the consumption device. The tokens that result are still OAuth/OIDC tokens (authorization + identity at the client).

06

How it composes

07

What bites agent implementers

  • Missing binding_message

    The user approves 'something' on the phone. For agent tool calls, the message must name the action.

  • Polling as a confused client

    auth_req_id without client authentication is stealable. Confidential client auth (or FAPI methods) on the token poll.

  • Using CIBA to skip consent policy

    CIBA authenticates/consents a grant; it does not replace RS policy or audience checks.

08

Stability — what you can ship

OIDF Final 2021 (errata revisions exist). Stable. https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html

Catalog claims (short form)

auth_req_id
Handle for the pending authentication.
binding_message
Short string shown on both agent UI and phone so the user knows which action they are approving.

Implementer notes

FAPI 2.0 Security Profile supports CIBA and notes that authorization-code and CIBA have been through detailed security analysis. Use CIBA for 'agent wants to do X while the user is away'; use XAA for 'IT already authorized this app connection'; use AAuth missions for natural-language, multi-resource intent.

Related

Primary sources

  • CIBA Corehttps://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html