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.
- G32 CIBA
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.
source ~/btl-oidc.sh. You need alab-collagerefresh token withopenidin its scope, as in Request offline access and compare refreshed ID tokens.Once G32 exists:
lab-tmp-kioskas in Sign in on one device and approve on another, with its ID inKIOSK_IDand its secret read withread -rs KIOSK_SECRET.
Planned walkthrough
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.
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.
After approval, the next poll returns
access_tokenandid_token. Validate the ID token withlab-tmp-kioskas the audience and no nonce, then use itsissandsub, never the typed email.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
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.
An ID token with no nonce, validated by how it arrived. Refresh with
lab-collageand 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.
Write the kiosk's rule in your notes: whose albums to show comes from the validated
issandsub, 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_supportedand the CIBA grant in discovery.