How JWT expiration works
July 15, 2026 · 14 min read
JWTs expire because self-contained tokens cannot be revoked instantly without extra infrastructure. Time claims exp and nbf bound the valid window in Unix seconds (UTC). Misconfigured clocks and missing leeway cause flaky 401s that look like random auth failures.
Time-related claims at a glance
iat- issued at; useful for audit, not usually enforced as a hard gate.nbf- not before; reject token if current time is earlier than this.exp- expiration; reject if current time is at or after this (per library rules).
{
"sub": "user_42",
"iat": 1718701200,
"nbf": 1718701200,
"exp": 1718704800
}
The exp claim in production
Access tokens commonly live 5–15 minutes; ID tokens may be shorter. Always set exp at issue time - never rely on clients to discard tokens. APIs should fail closed: expired token means 401, not partial access. Log exp minus server time in debug mode to spot skew quickly.
nbf and scheduled activation
nbf delays validity until a future moment - useful for pre-issued tokens or maintenance windows. Fewer validators enforce nbf than exp; enable both in your library for symmetry. If nbf is in the future, treat the token as invalid even if exp is far ahead.
Clock skew and leeway
Servers, laptops, and containers drift. NTP keeps most systems within seconds, but VMs restored from snapshots may jump. Libraries support leeway (e.g. 30–60 seconds) added to exp and subtracted from nbf so minor skew does not break auth. Do not set leeway to minutes - that widens replay windows.
import jwt
from datetime import timedelta
payload = jwt.decode(
token,
key,
algorithms=["HS256"],
leeway=timedelta(seconds=30),
options={"require": ["exp", "sub"]},
)
Refresh tokens and rotation
Short exp limits stolen-token damage but annoys users if login is frequent. Issue a long-lived refresh token (opaque or JWT) stored securely; exchange it for new access tokens. Rotate refresh tokens on each use and detect reuse to catch theft. Decode access tokens locally to confirm new exp after refresh.
FAQ
- Are JWT exp times UTC?
- Yes. exp and nbf are NumericDate seconds since Unix epoch in UTC. Display layers convert to local time.
- What leeway should I use?
- Typically 30–60 seconds. Increase only if you have proven clock sync problems, and monitor NTP on servers.
- Can a token be valid after exp if the signature verifies?
- No compliant verifier should accept it. Signature proves integrity, not that time claims are still satisfied.
- Should refresh tokens have exp?
- Yes. Longer than access tokens, but bounded. Pair with rotation and revoke on logout.
Related: Debug invalid JWT errors