Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

Poll, ping, and push modes

All domains, identifiers, and tokens in these examples are fictional. Readable values make the example easy to follow. Real ones are long and random.

The kiosk in Following a CIBA exchange asked the token endpoint every five seconds until you approved. That works, but the printing company runs kiosks in hundreds of shops, and most of those requests come back with nothing but "not yet". Meanwhile you stand at the kiosk for up to five seconds after approving, waiting for its next request.

CIBA offers three ways to deliver a result, called token delivery modes. The client chooses one when it registers, and the provider delivers results only in that mode.

Polling for the result

In poll mode, the client asks the token endpoint with the CIBA grant until it gets an answer, as the kiosk did. The rules are the ones the photo frame followed in Device authorization, and CIBA reuses that grant's error codes as well. The client waits at least interval seconds between requests, and after a slow_down it adds at least five seconds to the interval for the rest of the attempt.

CIBA spells out a few more details. The interval is measured from the moment each request is sent, and the client never has two requests for the same auth_req_id in flight: it waits for each answer before sending the next. A provider may hold a request open until the result is ready or about thirty seconds have passed, a technique called long polling, so the kiosk should be prepared to wait that long for a reply. A provider under heavy load may answer with status 503 and a Retry-After header, which the kiosk respects. And a client that keeps polling faster than the interval may receive invalid_request, after which it must stop asking about that request altogether.

Poll mode asks the least of the client. Every request goes out from the kiosk's servers to the photo service, so nothing has to reach the printing company from outside. The costs are the stream of empty answers and the delay between your approval and the kiosk's next request.

A ping when it is ready

In ping mode, the photo service tells the client when there is something to collect. The printing company registers a client notification endpoint, an HTTPS address of its own, as the client's backchannel_client_notification_endpoint. Each backchannel authentication request then carries one more parameter, client_notification_token:

POST /bc-authorize HTTP/1.1
Host: auth.photos.example
Content-Type: application/x-www-form-urlencoded

scope=openid%20photos.read
&login_hint=robin%40mail.example
&binding_message=H4PX
&client_notification_token=demo-notification-token-8
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJFUzI1NiIsImtpZCI6Imtpb3NrLTIwMjYtMTAiLCJ0eXAiOiJKV1QifQ...

The notification token is a bearer token that the kiosk creates for this one request and the photo service presents when it calls back. It runs in the opposite direction from the tokens you have met so far: the client issues it, and the provider uses it. A real one is random, with at least 128 bits of entropy, and at most 1,024 characters long.

When you approve, or decline, the photo service posts to the notification endpoint:

POST /ciba/notify HTTP/1.1
Host: kiosk.printer.example
Authorization: Bearer demo-notification-token-8
Content-Type: application/json

{
  "auth_req_id": "demo-auth-req-21"
}

The kiosk's servers check that the bearer token is the one they created for demo-auth-req-21, and answer 401 if it is not. A valid ping gets 204 No Content, never a redirect. The ping says only that a result is ready, not what it is. It is sent after a refusal as well as an approval, so the kiosk then makes the same token request as in poll mode and receives either the tokens or an error such as access_denied.

Because the ping carries no result, a forged or replayed one can do little. At worst it makes the kiosk ask the token endpoint early and receive authorization_pending. Results still come only from the token endpoint, after client authentication. The photo service need not send a ping when a request simply expires, since the kiosk already knows the deadline from expires_in, so the kiosk keeps its own timer and gives up when it passes. A client in ping mode may also poll, for example to recover from a notification that never arrived, and the provider then treats it as it would a polling client.

Tokens pushed to the client

In push mode, the photo service skips the token request altogether and posts the result itself to the notification endpoint:

POST /ciba/notify HTTP/1.1
Host: kiosk.printer.example
Authorization: Bearer demo-notification-token-8
Content-Type: application/json

{
  "auth_req_id": "demo-auth-req-21",
  "access_token": "demo-access-token-30",
  "token_type": "Bearer",
  "expires_in": 600,
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InBob3Rvcy1ycy0yMDI2LTA5IiwidHlwIjoiSldUIn0..."
}

The ID token is shortened here for display. Push saves a round trip, but it changes how the tokens reach the client. In every other flow, the client collects its tokens from the token endpoint, on a connection it opened itself, after authenticating. Here the tokens arrive at an endpoint the client exposes to the internet, protected only by the notification token. CIBA makes up for that by having the signed ID token vouch for the rest of the message. In push mode, it must carry extra claims:

{
  "iss": "https://auth.photos.example",
  "sub": "user-2048",
  "aud": "printer-kiosk",
  "iat": 1791036100,
  "exp": 1791036400,
  "at_hash": "xAu1dOkzBWNjOd-hrec1Xw",
  "urn:openid:params:jwt:claim:auth_req_id": "demo-auth-req-21"
}

at_hash is a hash of the access token: the left half of its SHA-256 hash, Base64url-encoded, with SHA-256 chosen because the token is signed with RS256. The claim with the long URN name repeats the request identifier. Had the photo service also delivered a refresh token, a third claim, urn:openid:params:jwt:claim:rt_hash, would hash that too. The kiosk checks the notification token, validates the ID token as usual, confirms that its auth_req_id claim matches the identifier in the message, and recomputes the access token's hash to compare with at_hash. Only then does it use anything in the message.

Failures arrive the same way, as a message with error and auth_req_id: access_denied if you declined, transaction_failed if something else went wrong, and possibly expired_token if time ran out, although providers are not obliged to send that one. A client registered for push never calls the token endpoint with the CIBA grant. If it tries, it receives unauthorized_client.

Push is the mode you are least likely to meet. The FAPI security profile for CIBA, written for financial services and other higher-risk uses, does not permit it, because it departs from the established pattern of collecting tokens from the token endpoint with client authentication, and that departure may carry risks nobody has found yet. CIBA itself advises deployments that use push to consider sender-constrained access tokens, such as the certificate-bound access tokens of mutual TLS, so that a token intercepted on its way to the client is useless to anyone else.

Choosing a mode

The photo service publishes the modes it supports in its discovery document, and the kiosk's registration records the one mode it will use:

Photo service metadata (excerpt):
{
  "issuer": "https://auth.photos.example",
  "backchannel_authentication_endpoint": "https://auth.photos.example/bc-authorize",
  "backchannel_token_delivery_modes_supported": ["poll", "ping"]
}

Registration for printer-kiosk (excerpt):
{
  "token_endpoint_auth_method": "private_key_jwt",
  "jwks_uri": "https://kiosk.printer.example/jwks",
  "grant_types": ["urn:openid:params:grant-type:ciba"],
  "backchannel_token_delivery_mode": "ping",
  "backchannel_client_notification_endpoint": "https://kiosk.printer.example/ciba/notify"
}

A client in poll or ping mode lists the CIBA grant in its grant_types, because it will use the token endpoint, and a provider that supports those modes lists the grant among its supported grant types. A client in ping or push mode must register its notification endpoint, which must use HTTPS. The provider should make sure that endpoint is genuinely under the client's control, or it could deliver someone's result to the wrong party. One registration field covers authentication everywhere: token_endpoint_auth_method applies at the backchannel authentication endpoint as well as at the token endpoint.

ModeWhere the result comes fromWhat the client must runMain trade-off
pollThe token endpoint, whenever the client asksNothing beyond outgoing requestsMany empty answers, and a delay of up to one interval
pingThe token endpoint, after a notificationAn HTTPS notification endpoint the provider can reachOne more endpoint to run and protect, in exchange for prompt results
pushThe notification itselfAn HTTPS endpoint that accepts tokensNo authenticated token request, so more checks fall to the client

The printing company started with poll, because it needed nothing beyond the requests its kiosk service already makes. Once that service could run a notification endpoint reliably, ping let each kiosk react the moment you approve, while the tokens still come only from the token endpoint. The photo service does not offer push, and the printing company has no reason to want it: saving one request per customer is not worth the extra checks and exposure.

Try it in the Lab

PUT IT INTO PRACTICE

Check your understanding

Try these questions before moving on. If an answer isn't right, use the feedback and try again.

0 of 2 answered correctly

Enable JavaScript to answer these questions and save progress in this browser.

QUESTION 1 OF 2The kiosk's notification endpoint receives a ping with the correct notification token for demo-auth-req-21. What should the kiosk do next?

QUESTION 2 OF 2In push mode, why must the ID token contain at_hash and the auth_req_id claim?

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

Learn identity