Pick a JWT exp claim: validity window with clock skew, when to refresh early, and how long a revoked token stays accepted.
Verifiers usually accept a token for a little past its exp to tolerate clock drift, so the real validity window is the lifetime plus that leeway on each end. Refreshing at a fraction of the lifetime keeps a valid token in hand at all times instead of racing the expiry. The exp claim is the only revocation mechanism a stateless JWT has, so its value is literally the length of time a compromised or logged-out session keeps working.
JWT Expiry
validity = (exp − iat) + clock skew leeway; refresh at (exp − iat) × (1 − refresh margin) so a renewal is in flight before the token dies.
Revocation exposure
stale access after revocation = validity window, since a verifier that only checks the signature cannot learn the token was withdrawn.
validity = (exp − iat) + clock skew leeway; refresh at (exp − iat) × (1 − refresh margin) so a renewal is in flight before the token dies. Verifiers usually accept a token for a little past its exp to tolerate clock drift, so the real validity window is the lifetime plus that leeway on each end. Refreshing at a fraction of the lifetime keeps a valid token in hand at all times instead of racing the expiry.
The exp claim is the only revocation mechanism a stateless JWT has, so its value is literally the length of time a compromised or logged-out session keeps working.
This calculator takes 5 inputs: Token lifetime (exp − iat), Clock skew leeway allowed by verifiers, Refresh this far before expiry, Session length to cover, Requests per minute per client. The pre-filled defaults are a realistic starting point — replace them with figures from your own environment for a result you can act on.
Thirty to sixty seconds is typical and most libraries default to that range. Larger values silently extend every token's life, so if servers are NTP-synchronised there is little reason to go beyond a minute — and none to disable expiry checking to work around a drifting clock.
Not in the token itself. You need server-side state: a deny-list of jti values checked on each request, a token-version claim compared against the user record, or an introspection call. All three trade the statelessness that made JWTs attractive, which is why short lifetimes remain the usual answer.