Reading a JWT's Real Lifetime: Epoch Arithmetic on iat and exp

Web & API Security Level 2/4 ~3 min September 9, 2026

The challenge

You pulled a refresh token out of a mobile app's storage during a review. Refresh tokens are the high-value target in any mobile auth flow, because a stolen one keeps minting fresh access tokens for as long as it stays valid, and the answer to how bad that is comes down to a single number: its lifetime. The token will not tell you that number directly. It carries two Unix epoch timestamps, one for when it was issued and one for when it expires, and the gap between them is the answer. Decode the payload, subtract, convert seconds into days, and submit the number of days this token stays valid.

What you'll learn

  • Decode a JWT payload without any key and read its registered claims
  • Interpret iat and exp as Unix epoch seconds
  • Convert a claim difference into a human-readable lifetime
  • Assess refresh token lifetime as a measure of exposure window
  • Spot the absence of device binding in a long-lived token

Skills tested

JWT analysisEpoch time arithmeticAuthentication design review

Prerequisites

  • Knowing a JWT payload is encoded rather than encrypted
  • Basic arithmetic with Unix timestamps

How it works

Reading a claim out of a JWT is a lookup. Judging a token means doing arithmetic on its claims, and the most important number in an authentication review is rarely written down anywhere: how long a stolen credential stays useful.

A JWT has three dot-separated segments and the payload is base64url encoded, not encrypted, so it decodes with no key. Two registered claims matter here. iat is issued-at and exp is expiry, both Unix epoch seconds counted from 1 January 1970 UTC. Neither is human-readable on its own, and the token deliberately does not state its lifetime.

This payload carries iat of 1788858900 and exp of 1796634900. The difference is 7776000 seconds, and dividing by 86400 gives exactly 90 days, spanning 8 September to 7 December 2026.

Scope makes that number serious. This is a refresh token, whose entire job is to mint new access tokens. A short-lived access token limits damage to minutes; a refresh token with a ninety day life hands an attacker a renewable key to the account for a quarter of a year. The payload also has no device or installation claim, so nothing ties it to the handset it was issued to, and it can be replayed from anywhere. The jti is the one hopeful sign, but a token identifier only helps if the server keeps a revocation list and checks it on every exchange.

Common mistakes

  • Submitting an epoch value. 1796634900 is the expiry instant, not the lifetime. The answer is the difference between the two claims.
  • Dividing by the wrong constant. A day is 86400 seconds. Dividing by 3600 gives hours and by 60 gives minutes.
  • Answering in months. Ninety days is about three months, but the question asks for days.
  • Reading the exp claim as milliseconds. JWT epoch claims are in seconds; treating them as milliseconds makes the lifetime look negligible.
  • Assuming the signature has to be verified first. The payload is readable regardless, which is the underlying lesson about JWTs.

How to defend against it

The exposure window is a design choice, and ninety days is choosing to have one.

  • Keep refresh token lifetimes short, typically days rather than months, and re-authenticate rather than extend indefinitely.
  • Rotate refresh tokens on every use and detect reuse of a rotated token, which is the strongest available signal that one has been stolen.
  • Bind the token to the device or installation and reject it when presented from a different one, so theft alone is not enough.
  • Store refresh tokens in platform-backed secure storage, the Keychain or Keystore, not in shared preferences or a plist that lands in a backup.
  • Maintain a server-side revocation list keyed on jti and check it on every exchange, so logout and incident response actually terminate a session.
  • Keep access tokens minutes-long so that the refresh token is the only thing worth protecting, then protect it properly.

Full solution

Pro and Max members unlock the complete step-by-step walkthrough.

Go Pro

Community stats

173 completions
89% success rate
Malekith First blood

Related Daily Hacks

25,000+ Hackers 100+ Labs & Courses Free
Start Hacking Free