How to fix "jwt expired" and "token is not yet valid" errors

If a new token fails its time check, compare clocks before you touch code. A server running a few minutes off, or an exp written in the wrong unit, explains most cases.

Node's jsonwebtoken throws TokenExpiredError: jwt expired, PyJWT raises ExpiredSignatureError, and ASP.NET logs IDX10223. They all mean the same thing: the verifier's clock has reached the token's exp. When the token really is old, the fix is a refresh. When it was issued seconds ago, something else is wrong, and it's nearly always one of four causes.

By TechCompare · Updated

Topic
Fixing jwt expired
Expired token errors
Category
Pitfalls
Mistakes that let forged tokens through

How this is calculated

Start by pasting the failing token into the JWT Decoder and reading the Time claims card. If exp is in the past by hours or days, the client is reusing an old token, so look at your refresh logic and at caches that keep a token after it expires. If exp is only a little in the past, or nbf is a little in the future, the issuer's clock and the verifier's clock disagree. Containers and virtual machines drift when time sync isn't running, and a gap of a few minutes is enough to break short tokens. Fix the clocks with NTP, then add a small leeway in the verifier: clockTolerance in jsonwebtoken and jose, leeway in PyJWT, clockSkewSeconds in jjwt. ASP.NET's ClockSkew already defaults to 5 minutes, which hides drift but also means tokens live that long past exp. If exp shows a date far in the future, it was written in milliseconds, and the issuer needs a fix. If the decoder shows a time claim as a string, the issuer is writing quotes around the number. The last cause is a token lifetime that's simply too short for the request path, like a 1 minute token passed through a slow queue. Use the Time settings to try a leeway and see which setting makes the token pass.

Verdict

Keep leeway small, around 30 seconds to 2 minutes, and fix the clocks rather than raising it to hide the problem. Never extend a token by editing its exp, since that breaks the signature. Ask the issuer for a new token, or use a refresh token to get one.

More JWT scenarios

Frequently asked questions

What does "jwt expired" mean?
The verifier's current time is at or past the token's exp claim. The signature might be perfect, but the token's lifetime is over. Get a new token from the issuer or with a refresh token.
How much clock skew should I allow?
A small amount, like 30 seconds to 2 minutes, covers normal drift between servers that sync their clocks. RFC 7519 suggests no more than a few minutes. A large leeway lets stolen tokens keep working well after they should have died.
Why does a brand new token fail as not yet valid?
Its nbf or iat is ahead of the verifier's clock. The issuer's server is running fast or the verifier's is running slow. Sync both with NTP, and allow a small leeway for nbf.