skip to content

What does an OpenID Connect ID token's exp claim bound, and why is it not a relying party's session lifetime?

level: seniorimportance: should knowfreq 44%

answer

  1. a bound on one statement, not a timer
  2. seconds since the 1970 epoch
  3. consumed once, so the window is short
  4. small leeway for skew is a MAY
  5. your session lifetime is yours to set

basics

~20 s

The exp claim bounds acceptance of the login assertion itself: after that instant the ID token must not be accepted. The specification states it is unrelated to the lifetime of the authenticated session between relying party and provider, which the protocol never sets.

solid answer

~40 s

`exp` is a freshness bound on one statement, not a timer on anything else. It is expressed as seconds since 1970-01-01T00:00:00Z UTC, the current time must be before it for the token to be accepted, and implementers MAY allow a small leeway — usually no more than a few minutes — for clock skew. Because the ID token is consumed once, at login, that window is normally short. The specification says explicitly that the ID token's expiry is unrelated to the lifetime of the authenticated session between the relying party and the provider: how long your own application session lasts is an application decision the protocol does not make. Teams that conflate the two either sign users out every few minutes, or ask for absurdly long-lived login assertions to avoid it.

code

pseudocode · 11 lines
pseudocode
leeway = 120 seconds        // a MAY, for ordinary clock drift only

if now + leeway < token.iat then
    reject "issued in the future: the two clocks disagree"

if now - leeway >= token.exp then
    reject "the login assertion is no longer acceptable"

// the assertion has been consumed here; it is not kept as a credential
session.user = token.iss + "|" + token.sub
session.expires_at = now + application_session_lifetime   // an application decision

go deeper

for a junior

Recall that exp is the point after which the login statement must no longer be accepted, and that it is a time in seconds rather than a duration.

for a middle

Explain why the window is short — the token is consumed once at sign-in — and that the specification separates it from the session between relying party and provider.

for a senior

Diagnose from symptoms: an intermittent login loop on one host points at clock drift, and a five-minute logout points at an assertion being reused as a session credential.

for a principal

Own the policy split: assertion windows stay tight and uniform, session lifetimes are set per application against what it can do, and neither is tuned to fix the other.

## What the claim actually says `exp` is REQUIRED in an ID token. Its value is a number of seconds since 1970-01-01T00:00:00Z UTC — the same time representation the JWT container defines in **RFC 7519** — and the rule attached to it is narrow: the current time must be before `exp` for the relying party to accept the token. Implementers MAY allow some small leeway for clock skew, and the specification characterises that leeway as usually no more than a few minutes. That is the whole of it. `exp` governs **acceptance of this assertion**. It is not a timer on the access token beside it, not a timer on the user's session at the provider, and not a timer on the relying party's own application session. ## Why the assertion's window is short The ID token is consumed once. It arrives at the end of a login, the relying party validates it, reads who signed in, creates its own session and puts the token down. Nothing about the application's later operation depends on the ID token still being acceptable, so a window measured in minutes is ordinary and sufficient. A long-lived login assertion is not a feature: it is a statement that keeps being replayable long after the event it describes. ## The claim the specification is careful to make OpenID Connect states outright that the ID token's expiration time is **unrelated to the lifetime of the authenticated session between the relying party and the provider**. Two separate clocks are in play and the protocol sets only one of them: | Lifetime | Who decides it | Where it is visible | |---|---|---| | the ID token's acceptability | the provider, in the assertion | the `exp` claim | | the access token's validity | the authorization server | the token response, separately from the ID token | | the user's session at the provider | the provider's own policy | not carried in the ID token | | the relying party's application session | the application | nowhere in the protocol | The last row is the point. Nothing in this specification tells an application how long its own sign-in should last; that is a decision the application owns, informed by what the application does, not by a claim in a token it consumed at the door. ## Three failures that come from conflating them 1. **The five-minute logout.** A portal keeps the ID token, re-validates it on every request as its session check, and signs users out the moment `exp` passes. The mechanism is that the portal has adopted the assertion's freshness bound as its session policy. The fix is to stop treating a consumed assertion as a session credential. 2. **The twelve-hour login assertion.** Having discovered the first failure, a team asks the provider for very long-lived ID tokens so sessions survive the working day. The session problem is now solved by widening the window in which a stolen or captured login assertion is still accepted, which is the opposite trade to the one they wanted. 3. **The login loop nobody can reproduce.** Brand-new tokens are rejected as expired, on one host, intermittently. The mechanism is clock drift: the relying party's clock is ahead of the provider's, so `exp` has notionally passed on arrival — or `iat` sits in the future and a strict routine refuses it. It reproduces nowhere else because no other host's clock is wrong. The standing defences are time synchronisation on every host that validates tokens, and the small skew leeway the specification permits — which is a tolerance for ordinary drift, not a substitute for correct clocks. ## Related time checks worth knowing `iat` records when the provider issued the token, and the specification allows a client to use it to reject tokens issued too far away from the current time. That is a separate, optional limit with a practical benefit: it bounds how long a client must retain per-request values such as the nonce it is waiting to compare. Nothing in either claim reports when the user actually authenticated; that question is asked and answered by other members of the specification. ## What a good answer sounds like Say what `exp` bounds in one sentence, state that the specification explicitly divorces it from the relying party's session, and then give a failure with its mechanism — the portal that re-validates a consumed assertion, or the host whose clock is ahead. Naming the mechanism is what distinguishes someone who has operated this from someone who has read about it.

  • How much clock skew leeway should a relying party allow, and what is it for?
    The specification permits some small leeway, usually no more than a few minutes, and leaves the number to the implementer. It exists to absorb ordinary drift between two synchronised hosts, not to paper over an unsynchronised one. Widening it to tens of minutes extends the window in which an expired assertion is still accepted, so the real remedy for repeated skew failures is time synchronisation.
  • What is iat used for beyond curiosity, given that exp already bounds acceptance?
    A client may use `iat` to reject tokens issued too far away from the current time. That is a separate optional limit from the expiry check, and its practical benefit is bounding how long the client must keep per-request values — notably the nonce it is waiting to compare — since anything older than that limit will be refused regardless.
  • A team wants sessions that survive the working day. What should change?
    Their own session policy, not the ID token. The assertion is consumed at login and its expiry should stay short; how long the application keeps someone signed in, and when it sends them back to the provider to be re-authenticated, is an application decision the protocol deliberately leaves open. Lengthening the login assertion only widens its replay window.

saying these in an interview costs you the question

  • The ID token's exp is how long the user stays logged in.
  • Re-validate the stored ID token on every request as the session check.
  • Ask the provider for longer-lived ID tokens to avoid re-login.
  • The access token expires when the ID token does.
  • Allow an hour of clock skew so expiry errors stop.
  • exp tells you when the user last authenticated.