OPENID CONNECT · LAB
Watch the provider session from the relying party
Plan polling the tenant's check session frame and reacting to changed, and today run the top-level silent check that session management depends on and see why the frame design fails cross-site.
PlannedUses your lab tenant
The lesson
Builds on: Front-channel logout.
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.
- G17 OIDC logout: RP-initiated, front-channel, back-channel, session management
Request console
Requests in this lab can be sent from this page to your tenant: open one and choose Send. Fill in the values below first. They stay in this page's memory and are gone when you leave; secrets are never stored or sent anywhere except the request you send.
Setup
Your tenant returns no session_state in authorization responses and has no check session frame yet (G17). The step that changed triggers, a silent check with the earlier ID token as a hint, is real today.
source ~/btl-oidc.sh, runbtl-lab callbackbefore each request, and sign Ava in tolab-collagein your lab browser. Keep her ID token:AVA_COLLAGE_ID_TOKEN=$ID_TOKEN.Once G17 exists: enable session management for
lab-collage.
Planned walkthrough
Sign in to
lab-collage. The listener showssession_statebesidecode,stateandiss. Store it with the session.Serve a page with two hidden frames: the tenant's
check_session_iframe, and your own asking frame, which posts"<client_id> <session_state>"to the tenant's origin every five seconds and accepts replies only from that origin.
const providerOrigin = new URL(issuer).origin;
setInterval(() => providerFrame.postMessage(clientId + ' ' + sessionState, providerOrigin), 5000);
window.addEventListener('message', event => {
if (event.origin !== providerOrigin) return;
if (event.data === 'changed') checkWithProvider();
});
Replies are
unchangeduntil you sign out of the tenant in another tab. Then the reply ischanged, and your page sends a top-levelprompt=nonerequest withid_token_hint.
Why it matters: changed is not a sign-out. It only says the provider's browser state differs, so the page must ask properly.
Serve the same page from a site other than the tenant's. The replies are
changedforever, and a client that obeys each one loops.
Do today
Confirm the frame is honestly unavailable.
GET$ISSUER/oidc/check_session
Open in console
GET $ISSUER/oidc/check_sessionThe answer is 501 temporarily_unavailable, and your callbacks carry no session_state.
The check that
changedwould trigger, done at the top level. With Ava signed in:
signin prompt=none "id_token_hint=$AVA_COLLAGE_ID_TOKEN"
A code comes back, and a new ID token for Ava: carry on.
Sign out of the tenant in another tab and repeat step 2:
error=login_required. End your app's session and stop the "timer".Sign in as Ben in another tab and repeat step 2:
error=login_required, and Audit records the reasonid_token_hint_mismatch. Without the hint you would get a valid ID token for Ben, which session management treats as a sign-out of Ava.
Why it matters: the hint is what turns "someone is signed in" into "the person this session belongs to is signed in".
Repeat step 2 inside a frame, as the frame design does:
printf '<iframe src="%s" width="600" height="200"></iframe>\n' "$(signin prompt=none "id_token_hint=$AVA_COLLAGE_ID_TOKEN")" > frame.html
Open frame.html as a local file while Ava is signed in. Audit records login_required every time. A client that answered each failure with another silent check would loop forever, so add the guard from the lesson: at most one silent check per page visit, then a signed-out screen that waits for the person.
Why it matters: the frame design depends on third-party cookies. Top-level checks, back-channel messages and your own server-side session are what still work.
Break it
Planned, once G17 exists: remove the event.origin check from the asking frame and post unchanged to it from another of your own local pages. The frame accepts the false answer and keeps a signed-out session alive. Put the origin check back.
Check your work
Today: in Audit, for lab-collage, one code_issued for Ava, then login_required after the sign-out, id_token_hint_mismatch while Ben was signed in, and login_required for every framed attempt.
Once G17 exists, your page's log of unchanged and changed replies, followed by one top-level prompt=none event per changed.
Cleanup
Delete frame.html. Sign Ben out and Ava back in.
Missing infrastructure
G17 (OIDC logout).
session_statein authorization responses, the check session frame at/oidc/check_session(catalogued today, answering 501), andcheck_session_iframein discovery. With it, the planned walkthrough runs as written.