Establishing an application session
All domains, identifiers, and tokens in these examples are fictional, and the session identifiers are readable stand-ins for unpredictable random values.
On 1 October, a few days after linking your photo account, you open printer.example to start a new photo book. The printer asks you to sign in, and you choose Continue with your photo account. The photo service authenticates you at 08:59:45, and by 09:00:02 the printer has exchanged demo-code-12, validated the ID token against demo-nonce-3, and found account 8812 through your photo identity.
The sign-in is complete, but nothing yet connects your next click to it. The ID token is evidence that the photo service authenticated you a few seconds ago. Carrying that result from one request to the next is the printer's own job, and it is the job Staying signed in described: a session.
After validation
Your browser already had a printer session before you chose Continue. It was an anonymous one, created when you arrived, and it held the pending sign-in: state, nonce, PKCE verifier, and the page you were on.
Cookie: __Host-printer-session=demo-session-30
That session carried the attempt out to the photo service and back, so it is tempting to mark it as signed in when the callback succeeds. Staying signed in explained why that is a mistake. If an attacker had planted demo-session-30 in your browser, keeping the identifier would give them your account the moment you signed in. The printer finishes in a fixed order instead:
- Take the return page from the pending sign-in, then delete the pending sign-in so its
stateand nonce can never be used again. - Create a new session for account 8812 with a new random identifier, and invalidate
demo-session-30on the server. - Send the browser to the return page with the new session cookie.
The response to the callback carries the new cookie and the redirect together:
HTTP/1.1 302 Found
Location: /books/new
Set-Cookie: __Host-printer-session=demo-session-31; Path=/; Secure; HttpOnly; SameSite=Lax
The cookie has the attributes Staying signed in introduced, and it holds only an identifier. The ID token, the claims, and the account number all stay on the server.
The Location header deserves its own check. You were on /books/new when the printer asked you to sign in, and the printer recorded that path in the pending sign-in when you chose Continue. It does not take the destination from the callback's address, or from a parameter someone could add to a sign-in link. A printer that redirected wherever it was told could be used to send people from a genuine sign-in straight to a look-alike page that asks for their card details. The recorded value is checked as well: resolved against https://printer.example, it must keep that origin, which rules out values such as //attacker.example. Anything else falls back to the account home page.
Three different lifetimes
At 09:00:02, three different things could each be described as you being signed in. Each has its own clock, and each is controlled by a different party:
| What | Where it lives | Began | Ends |
|---|---|---|---|
| The photo service's session | A cookie for auth.photos.example that only the photo service can read | 08:59:45, when you authenticated | When the photo service's own policy says, possibly weeks later |
| The printer's session | demo-session-31, recorded on the printer's server | 09:00:02 | After two hours without activity, or seven days at most, under the printer's policy |
| The ID token | The printer's server, as evidence of one sign-in | Issued at 09:00:00 | Accepted only until 09:05:00, its exp |
The ID token's five minutes cause the most confusion. They limit how long the printer may accept this token as evidence of this sign-in, which it did at 09:00:02. They say nothing about how long you stay signed in. A printer that ended your session at 09:05 would sign everyone out after five minutes. The printer's session timeouts are its own decision, based on what it protects, as Staying signed in described.
The two sessions are just as independent of each other. The printer cannot see the photo service's session, and the photo service cannot see the printer's. If you sign out of the printer at 09:30, your photo service session continues, so choosing Continue with your photo account again may sign you straight back in without being asked for anything. That is single sign-on working as designed, though it can look as if signing out failed. Signing out of the photo service, in turn, leaves the printer session running. Logout and session coordination looks at how the printer and the provider can tell each other when a session ends.
There is one more clock in the sign-in. The access token, demo-access-token-12, lasted ten minutes, and the printer used it once to fetch your profile from UserInfo. It has no further use for it, so it is not kept at all.
What the session records
The session record on the printer's server holds what the printer will need later, taken from the validated ID token rather than from anything the browser sends:
Session demo-session-31
Account: 8812
Signed in with: https://auth.photos.example, subject user-2048
Authenticated at: 2026-10-01 08:59:45 UTC (auth_time)
Authentication context: none in this ID token (acr)
Provider session: none in this ID token (sid)
ID token: kept for a later logout request
Created: 2026-10-01 09:00:02 UTC
Last activity: 2026-10-01 09:00:02 UTC
Idle deadline: 2026-10-01 11:00:02 UTC
Absolute deadline: 2026-10-08 09:00:02 UTC
The account is what every later request is authorized against. Signed in with records which identity opened the session, which matters once an account has several. If you remove a link, as Linking accounts described, the printer can find and end the sessions that link opened.
Authenticated at is the ID token's auth_time, not the session's creation time, and the two can be far apart. Here they are seventeen seconds apart, because the photo service had just asked you to authenticate. If you had signed in to the photo service the evening before, it could have answered this request from that session without asking you anything, and auth_time would say the evening before, even though the printer session began at 09:00:02. When the printer later wants a recent sign-in before changing your delivery address, this is the value it compares with the clock. Session age and reauthentication follows that check.
The authentication context is empty because the printer did not ask for one and the photo service did not include an acr claim. When a provider reports one, the session keeps it, so a later decision can check how you signed in without asking again. Authentication context and methods explains what those values mean and who defines them.
The provider session is empty too. A provider that sends logout notifications can include a sid claim in the ID token, naming its own session for this sign-in. The printer stores it so that a later notice saying that session has ended can find the matching printer session. The printer registers for the photo service's notices in Local logout and provider sessions, and the claim appears there.
The ID token itself is kept on the server, never in a cookie or a page, for one reason. When you sign out, the printer can send it back to the photo service as a hint about which sign-in is ending, which RP-initiated logout describes. It is not read again to decide who you are. The session record already says that.
The timestamps enforce the idle and absolute timeouts. The idle deadline moves forward with each request, and the absolute deadline does not. When either passes, the session ends, whatever is happening at the photo service.