Session age and reauthentication
All domains, identifiers, and tokens in these examples are fictional.
At 15:00 UTC on 2 October you decide the photo book should go to your office instead of your home, and you open the printer's delivery address page on your computer. You have been signed in to the printer since the silent check at 08:00, coming back to the photo book every hour or so, often enough that its two-hour idle timeout never ran out. To the printer, nothing about this visit looks unusual.
When a recent sign-in matters
The delivery address decides where a parcel of your photos goes. Someone who sat down at your unlocked computer, or who had copied your printer session cookie, could send the order to themselves in a few clicks. Deleting your printer account is similar, and it cannot be undone. For actions like these, the printer wants more than a valid session. It wants evidence that you, the person who can sign in to your photo account, did so recently.
Authentication policy and SSO called this reauthentication: asking for a fresh check rather than a stronger one. The printer's rule is short. Changing the delivery address or deleting the account needs a sign-in from the last five minutes.
Its session record shows how far away that is:
| Session field | Value |
|---|---|
| Account | 8812 |
| Signed in with | https://auth.photos.example, subject user-2048 |
| Session created | 08:00:00 UTC on 2 October |
auth_time | 1790845185, which is 08:59:45 UTC on 1 October |
The session is seven hours old, but the sign-in behind it is more than thirty hours old. The silent check this morning created a new printer session without a new authentication, and the printer recorded the original auth_time, as it should. Nothing since then has moved that time forward, and nothing the printer does on its own, such as refreshing the calendar connection, ever could.
Requesting a fresh sign-in
The printer holds your new address as a pending change, stored on its server with the attempt, and sends you to the photo service:
https://auth.photos.example/authorize
?response_type=code
&client_id=photo-printer
&redirect_uri=https%3A%2F%2Fprinter.example%2Fsignin%2Fcallback
&scope=openid
&state=demo-signin-6
&nonce=demo-nonce-6
&code_challenge=zIg1QZV-I3GegEGQK73TUZpKR-4vRsAH1XMK4FTxM7Q
&code_challenge_method=S256
&max_age=300
&id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6InBob3Rvcy1ycy0yMDI2LTA5IiwidHlwIjoiSldUIn0...
The ID token hint is shortened. The scope is only openid, because the printer needs a sign-in, not another copy of your profile.
max_age, which the Step-up authentication challenges lessons in Advanced OAuth met as a requirement an API can send back, is the maximum authentication age, in seconds. It tells the photo service how long ago you may have last actively authenticated, by entering a password or using a passkey, for the request to be satisfied without asking again. If more time has passed, the photo service must try to authenticate you again. Either way, the ID token it returns must include auth_time. The id_token_hint from Login hints makes sure the fresh sign-in is for the account this session belongs to.
The photo service sees that your last sign-in was thirty hours ago and asks for your password. You enter it at 15:00:20, and the printer receives a new ID token:
{
"iss": "https://auth.photos.example",
"sub": "user-2048",
"aud": "photo-printer",
"iat": 1790953225,
"exp": 1790953525,
"auth_time": 1790953220,
"nonce": "demo-nonce-6"
}
Had you signed in to the photo service two minutes earlier for some other reason, the same request would have come back without a page, and auth_time would show those two minutes. That is what a maximum age offers over a demand for a new sign-in: it asks for exactly the freshness the printer needs and no more.
The other way to ask is prompt=login, from Prompt and account selection, which asks the photo service to authenticate you again however recent your session is. The specification treats max_age=0 as equivalent. The difference lies in what comes back. Any request with max_age, including max_age=0, must receive auth_time. A request with only prompt=login is not guaranteed to, and without it the printer cannot tell whether a new sign-in took place.
A client can close that gap in other ways. It can ask for auth_time as an essential claim through the claims parameter, or rely on two settings from Registering a relying party. require_auth_time set to true makes the photo service include auth_time in every ID token issued to the printer, which also gives its session records a reliable value from the first sign-in. default_max_age applies a maximum age to every request that does not carry its own, and a max_age in the request overrides it. The printer sets require_auth_time but not default_max_age, because only a few of its actions need a recent sign-in, and an ordinary visit should not.
Checking auth_time
The printer asked for max_age=300, but it does not assume the photo service honored it. The request passed through your browser, where whoever controls the browser can edit it. Someone at your unlocked computer could stop the redirect, delete max_age, and send the rest on. The photo service would see an ordinary request, reuse your session, and return a valid ID token whose auth_time is still 1 October. A provider that mishandled the parameter would produce the same result. Only the printer's own check catches both.
After the usual ID token validation, including the nonce demo-nonce-6, the printer adds checks of its own:
claims = validate_id_token(response, pending) # signature, issuer, audience, times, nonce
if (claims.iss, claims.sub) != (session.iss, session.sub):
reject() # someone else signed in
if claims.auth_time is None:
reject() # max_age was sent, so it must be present
if now() - claims.auth_time > pending.max_age + CLOCK_TOLERANCE:
reject() # not recent enough
session.auth_time = claims.auth_time
apply(pending.change)
The subject comes first. Reauthentication means the person who owns this session proved themselves again. If the token names a different account, someone else signed in at the photo service, perhaps deliberately. The printer must not apply your pending change on their sign-in. The safest response is to discard the change and end the session, so whoever is at the keyboard has to sign in as themselves.
A missing auth_time is a failure, not a pass, because the photo service was required to include it. The age check allows a small tolerance for differences between the two servers' clocks, measured in seconds, never enough to turn five minutes into an hour. At 15:00:25 the new token's auth_time is five seconds old, well inside the limit.
Then the printer records the new auth_time in the session, so a second change a minute later needs no further trip, and applies the change. The rule lives on the printer's server, where the change is submitted. A request that reaches the address endpoint without going through the page meets the same check.
If you cancel at the photo service, or cannot sign in, the printer receives an error instead of a code. Your session continues and the address stays as it was. The printer can explain that the change needs a recent sign-in and offer to try again.
A fresh password sign-in was all the printer needed. Some services need to know not only when someone signed in but how, and Authentication context and methods turns to the claims that describe that.