How to Fix JWT Signature and Expiry Errors
An invalid signature means the token was verified against a different key from the one that signed it, or with a different algorithm. Expired means the exp claim is in the past, sometimes only because of clock skew between servers. Malformed means the string is not three dot-separated Base64url segments. Decoding a token proves none of these.
JWT Decoder
Read a JSON Web Token header, payload and expiry.
Verification failures are rarely subtle once you separate the three rejections. Each one fails at a different stage: malformed fails before any crypto happens, invalid signature fails during it, and expired fails after the signature has already been accepted.
Decoding is not verifying. A decoder reads the header and payload without checking anything, which is exactly why it is useful for diagnosis — you can see the claims of a token your server is rejecting, including which key it says it was signed with.
Step by step
-
Decode the token and read the header
The alg claim tells you which algorithm signed it and kid, when present, tells you which key. A token signed with RS256 will never verify against an HS256 secret, and that mismatch is a common result of copying configuration between services.
-
Check how the secret is being interpreted
For HMAC algorithms the secret is a byte string. If one side treats it as UTF-8 text and the other Base64-decodes it first, the two produce different keys from the same configuration value and every signature fails. This is the most common cause of invalid signature.
-
Compare exp against real time
exp and iat are Unix timestamps in seconds, not milliseconds. Convert them and compare with the current time. A token that expired seconds ago on a server whose clock has drifted is a clock problem, not a token problem.
-
Confirm the token came from this environment
Staging and production almost always use different signing keys. A token pasted from the wrong tab, or a cached token surviving a key rotation, produces exactly the same invalid signature error as a genuine attack.
-
Count the segments before anything else
A malformed error means the string is not three Base64url segments separated by dots. Check for a Bearer prefix that was not stripped, a truncated value from a database column that was too short, or whitespace introduced by copying.
Example
The three segments of a JWT. Only the first two are readable; the third is the signature over them.
Token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZXhwIjoxNzAwMDAwMDAwfQ.signature
Decoded header and payload
header: { "alg": "HS256", "typ": "JWT" }
payload: { "sub": "1", "exp": 1700000000 }
Frequently asked questions
Why does my JWT show an invalid signature?
My token has not expired but is rejected as expired. Why?
Can I trust a JWT payload after decoding it?
Is it safe to paste a token into a decoder?
What does a malformed token error mean?
Tools used in this guide
All tools →- JWT Decoder Read a JSON Web Token header, payload and expiry. In your browser
- HMAC Generator Sign a message with a secret key using HMAC. In your browser
- Unix Timestamp Converter Convert between Unix timestamps and human dates. In your browser
- Base64 Encoder and Decoder Encode text to Base64 or decode it back, including URL-safe. In your browser
Related guides
All guides →- How to Decode a JWT Read the header and payload of a JSON Web Token, check its expiry, and understand why decoding is not verifying.
- JWT vs Session Cookies Stateless tokens or server-side sessions — and why revocation is the deciding factor.
- How to Verify a Webhook Signature Reproduce an HMAC signature correctly, and find out why yours does not match.
Last reviewed .