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

OPENID CONNECT · LAB

Run a CIBA poll-mode exchange

Plan a backchannel request, its acknowledgement and polling with the CIBA grant, and today confirm what discovery honestly offers and validate a real ID token that has no nonce by how it arrived.

PlannedUses your lab tenant

The lesson

Builds on: Separating the consumption and authentication devices.

New to the labs? Start with the lab toolkit and the shared cast and names every lab uses.

Planned. The core of this lab waits on platform features that are not built yet. The planned walkthrough shows exactly how it will run; Do today is a real exercise you can do now.

Setup

CIBA is not implemented yet (G32). The validation that replaces the nonce in a CIBA ID token can be practised today with a refreshed ID token, which also arrives with no nonce.

  1. source ~/btl-oidc.sh. You need a lab-collage refresh token with openid in its scope, as in Request offline access and compare refreshed ID tokens.

  2. Once G32 exists: lab-tmp-kiosk as in Sign in on one device and approve on another, with its ID in KIOSK_ID and its secret read with read -rs KIOSK_SECRET.

Planned walkthrough

  1. Ask the provider to reach Ava. The client authenticates at this endpoint too, and names her with exactly one hint:

curl -s -u "$KIOSK_ID:$KIOSK_SECRET" "$ISSUER/oidc/backchannel_authentication" -d "scope=openid" --data-urlencode "[email protected]" -d binding_message=H4PX

The acknowledgement comes at once: {"auth_req_id":"...","expires_in":120,"interval":5}. Keep auth_req_id on the server as REQ, never on the screen.

Why it matters: the provider answers before involving Ava, so errors in the request come back here, before her phone lights up.

  1. Poll no faster than interval, waiting for each answer before sending the next:

curl -s -u "$KIOSK_ID:$KIOSK_SECRET" "$ISSUER/oauth/token" -d grant_type=urn:openid:params:grant-type:ciba --data-urlencode "auth_req_id=$REQ"

authorization_pending until Ava approves on her phone.

  1. After approval, the next poll returns access_token and id_token. Validate the ID token with lab-tmp-kiosk as the audience and no nonce, then use its iss and sub, never the typed email.

  2. The errors before involving anyone: two hints (invalid_request), an unknown address (unknown_user_id), a client without the grant (unauthorized_client), and a wrong secret (invalid_client, status 401).

Do today

  1. Read what discovery honestly offers:

curl -s "$ISSUER/.well-known/openid-configuration" | jq '{backchannel_authentication_endpoint, grant_types_supported, ciba: .btl_endpoint_status["/oidc/backchannel_authentication"], device: .btl_endpoint_status["/oauth/device_authorization"]}'

No backchannel endpoint, no CIBA grant, and not_implemented for both CIBA and device authorization, the lesson's comparison flow (G5).

Why it matters: a client discovers what a provider supports before building a flow on it, and an honest provider lists nothing it cannot do.

  1. An ID token with no nonce, validated by how it arrived. Refresh with lab-collage and validate the refreshed ID token without a nonce:

RESP=$(curl -s -u "$CLIENT_ID:$CLIENT_SECRET" "$ISSUER/oauth/token" -d grant_type=refresh_token --data-urlencode "refresh_token=$REFRESH")
REFRESH=$(jq -r .refresh_token <<<"$RESP"); ID2=$(jq -r .id_token <<<"$RESP")
btl-lab verify "$ID2" --issuer "$ISSUER" --audience "$CLIENT_ID" --type id
part "$ID2" | jq '{sub, aud, nonce}'

It passes, and nonce is null. Only your authenticated client could redeem that refresh token, directly at the token endpoint.

Why it matters: a CIBA ID token has no nonce for the same reason. The request had no nonce parameter, and the redemption binding does that job: only the kiosk could redeem auth_req_id, after authenticating, and only once.

  1. Write the kiosk's rule in your notes: whose albums to show comes from the validated iss and sub, never from the email address someone typed on the screen.

Break it

Planned, once G32 exists: poll with an auth_req_id issued to another client and get invalid_grant; let two minutes pass and get expired_token. Both end the attempt, and the kiosk offers to start again.

Check your work

Today: discovery showed no CIBA support, and Audit shows an oauth.token success for lab-collage whose ID token you validated with no nonce.

Once G32 exists, Audit shows the request, the approval and the tokens issued, and Logs summarizes the authorization_pending polls.

Cleanup

Revoke the refresh token if you no longer need it. Once G32 exists, clean up as in the previous lab.

Missing infrastructure

  • G32 (CIBA). As in the previous lab, plus backchannel_authentication_endpoint, backchannel_token_delivery_modes_supported and the CIBA grant in discovery.

Back to all labs

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

The Lab