Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

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 fieldValue
Account8812
Signed in withhttps://auth.photos.example, subject user-2048
Session created08:00:00 UTC on 2 October
auth_time1790845185, 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.

Try it in the Lab

PUT IT INTO PRACTICE

Check your understanding

Try these questions before moving on. If an answer isn't right, use the feedback and try again.

0 of 2 answered correctly

Enable JavaScript to answer these questions and save progress in this browser.

QUESTION 1 OF 2At 15:00 the printer sends max_age=300. The returned ID token validates, but its auth_time is 08:59:45 the previous day. What should the printer do?

QUESTION 2 OF 2Why does the printer use max_age=300 rather than prompt=login before changing the delivery address?

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

Learn identity