JWT "Token Expired" Error, Explained
A token can have a perfectly valid signature and still be rejected — expiration is a separate check, and a signature never expires on its own.
What triggers it
JWTs carry an optional exp claim in the payload: a Unix timestamp (seconds since epoch) marking when the token stops being valid. Verification libraries check exp against the current time in addition to verifying the signature — a token signed correctly an hour ago with exp set to 10 minutes ago is a completely valid signature attached to data that says "don't trust me anymore."
{
"sub": "user-123",
"iat": 1753000000,
"exp": 1753003600
}
If the current time is past 1753003600, this token is expired — regardless of signature validity.
Why this is separate from signature verification
Signing proves the token wasn't tampered with since it was issued. Expiration is a policy decision baked into the payload at issue time, saying how long that proof should be trusted. Conflating the two is a common source of confusion: "the signature is valid" and "the token is still usable" are different questions, and most JWT libraries report them as distinct failure reasons for exactly this reason.
How to check it
Paste the token into the JWT Decoder — it checks exp against your local clock automatically and reports the exact expiry time alongside whether it's still valid, with an adjustable clock-skew tolerance for tokens issued by a server whose clock is slightly ahead or behind yours.