Using `session_state` and `check_session_iframe`, how does a relying party notice that the provider session has ended?
answer
- a digest, not a value you chose
- two hidden frames, one message channel
- per client and per origin
- check who sent the message first
- a change means re-check, not log out
basics
~20 sThe provider returns session_state with the authentication response and publishes check_session_iframe. The relying party loads that frame hidden and polls it by postMessage, comparing digests; a reported change is a prompt to re-check, never a logout instruction.
solid answer
~40 s`session_state` is a **digest the provider computes** — over the client identifier, the relying party's origin and an opaque provider-side session value, plus a salt — and returns alongside the authentication response. It changes whenever the provider's session for that user changes. The provider also publishes a `check_session_iframe` URL; the relying party loads it hidden and, from a hidden frame of its own, sends the client identifier and its last known `session_state` to it by `postMessage` at an interval the relying party chooses. The provider frame recomputes the digest from its own cookie and answers: unchanged, changed, or could-not-check. The relying party **must accept messages only from the provider frame's origin**, and a reported change is a signal to run a passive authentication check — not grounds to sign anybody out.
code
pseudocode · 18 linesfunction poll(providerFrame, clientId, lastSessionState, providerOrigin):
for each tick of the chosen interval:
send to providerFrame via postMessage:
payload = clientId + " " + lastSessionState
audience = providerOrigin
function onMessage(senderOrigin, payload):
if senderOrigin is not providerOrigin:
ignore
return
if payload reports the session unchanged:
return
if payload reports the session changed:
run a passive authentication check to confirm
if still authenticated:
lastSessionState = value from the new response
else:
treat the provider session as endedgo deeper
Recall that a relying party cannot read the provider's cookie, so it learns about a sign-out elsewhere by asking a hidden frame from the provider whether anything changed.
Explain the two frames, the digest and the message exchange, and why the answer is only ever a prompt to re-check rather than an instruction to end a session.
Demonstrate the operational side: the origin check as the mechanism's only real defence, the polling interval as a cost decision, and cross-site cookie behaviour as the thing that quietly disables it.
Judge whether to depend on polling at all. It costs battery and provider capacity on every open tab and rests on browser behaviour you do not control, which argues for notification as the primary mechanism.
## What `session_state` actually is `session_state` is returned beside the authentication response, not inside the ID token. It is a **digest**, computed by the provider over the client identifier, the relying party's origin and an opaque value representing the provider's current session for that user, together with a salt. Two properties follow from that construction, and both are the point: - It is **per-client and per-origin**. Two relying parties looking at the same provider session hold different `session_state` values, so the value leaks nothing between them. - It **changes when the provider's session changes**. The relying party cannot read the provider's cookie — nothing in a browser lets it — but it can tell that the digest over that cookie is no longer the one it was given. It is not a value the client chose and the provider echoed back. That is the `state` parameter, a different thing with a confusingly similar name. ## Two frames and a message channel The provider publishes a `check_session_iframe` URL in its configuration document. Session monitoring then works like this: 1. The relying party loads the provider's `check_session_iframe` in a hidden frame. Because it is loaded from the provider's origin, that frame — and only that frame — can see the provider's session cookie. 2. The relying party loads a hidden frame of its own, from its own origin, holding the last `session_state` it was given. 3. At an interval the relying party chooses, its frame sends a `postMessage` to the provider's frame containing the client identifier and that stored `session_state`, addressed to the provider's origin. 4. The provider's frame recomputes the digest from the cookie it can see and replies, by `postMessage`, with one of three outcomes. 5. The relying party's frame checks the sender's origin before looking at the payload at all, and acts only on a message from the provider's origin. | Outcome reported | What it means | What the relying party does | |---|---|---| | Session unchanged | The recomputed digest matches the stored one | Nothing; wait for the next tick | | Session changed | The digest differs — signed out, signed in as somebody else, or otherwise altered | Run a passive authentication check to find out which | | Check could not run | The frame could not compute an answer, typically because it could not see its cookie | Treat as unknown; do not infer a logout | ## The origin check is the security of the whole mechanism Any page that can obtain a handle to a frame can post a message to it. If the relying party's frame reads payloads without testing the sender, a hostile page can forge either answer, and both directions hurt: a forged 'unchanged' keeps a dead session looking alive on screen indefinitely, and a forged 'changed' drives needless re-authentication, which is a denial-of-service with a friendly face. The origin test is what turns a broadcast medium into a point-to-point channel, and it is the detail interviewers reach for. ## A change is a question, not an answer The most common design error is to log the user out on the first reported change. The digest tells you it is different, not why. The user may have signed out; they may have signed in as a second identity in the same browser; the provider may have refreshed its session for its own reasons. So the correct reaction is to ask the provider properly — a passive authentication attempt the provider is asked to answer without interacting with the user. If it comes back with an authenticated response, the session is alive and the relying party updates its stored `session_state`. If the provider answers that it cannot do so without interaction, the session really is gone. ## What the mechanism assumes about the browser All of this rests on one assumption: that the provider's frame, loaded cross-site inside the relying party's page, is sent the provider's session cookie. Where a user agent does not send cookies in that context, the provider's frame can compute nothing, and the check degrades to permanently reporting that it could not run. That is not a bug in anyone's code, and the cookie attributes and defaults that decide it are a separate subject. The practical consequence for a design discussion is worth stating plainly: session monitoring by polling is the **weakest** of the session mechanisms to depend on, and an estate that needs reliable sign-out builds on notification instead. ## Cost The interval is the relying party's choice and it is a real trade-off: a short interval detects a sign-out sooner and spends battery, main-thread time and provider capacity doing it, on every open tab, for every signed-in user, forever. A long interval is cheap and lets a stale screen live longer. There is no correct number, only a decision about how long a screen may lie.
- Why must the relying party's frame check the origin of every `postMessage` it receives?Because any page able to reach the frame can post to it. Without the check, a hostile page can forge 'unchanged' and keep a dead session looking alive, or forge 'changed' and force constant re-authentication. The origin test is what makes the channel point-to-point rather than open.
- What does a reported change actually tell the relying party?Only that the digest no longer matches what it holds. The user may have signed out, signed in as someone else, or the provider may have altered its session for its own reasons. It is grounds to re-check with a passive authentication request, not grounds to sign anyone out.
- Why is `session_state` computed per client and per origin rather than being one value for the session?So that the value handed to one relying party reveals nothing about the provider's session to another, and cannot be replayed between them. Each relying party can detect that its own digest changed without learning anything about the underlying session value or about who else is signed in.
saying these in an interview costs you the question
- Treats session_state as an opaque value the client chose
- Signs the user out on the first reported change
- Reads postMessage payloads without checking the sender's origin
- Thinks session_state is a claim inside the ID token
- Assumes polling works where cross-site iframe cookies are not sent