How to Fix "JWT Expired" and "Invalid Signature" Errors
JWT errors like TokenExpiredError, JsonWebTokenError, and invalid signature are the most common authentication debugging issues in web development. This guide explains every major JWT error, its specific cause, and how to fix it without exposing your tokens to third-party tools.
Table of Contents
- The 5 Most Common JWT Errors
- How to Debug a JWT Without Exposing It
- JWT Expiration — How Token Lifetime Works
- How to Prevent JWT Errors in Production
- FAQ
The 5 Most Common JWT Errors
Understanding the root cause of automated error messages is the first step toward a secure resolution. Below are the five most frequent issues developers encounter when working with JSON Web Tokens.
1. TokenExpiredError: jwt expired
- Cause: The
exp(expiration) claim in the token's payload contains a timestamp that is now in the past. The server correctly rejects the token as it is no longer valid. - Fix:
- Sync Server Clocks: Ensure your application servers and authentication servers are using synchronized NTP clocks. Even a few seconds of drift can cause immediate expiration.
- Increase Token Lifetime: Adjust the
expiresInsetting during token signing (e.g., from15mto30m) if the window is too narrow for user activity. - Refresh Tokens: Implement a refresh token pattern to allow users to obtain a new access token seamlessly without re-logging.
2. JsonWebTokenError: invalid signature
- Cause: The cryptographic signature at the end of the JWT does not match the content of the header and payload when verified with the provided secret or public key.
- Fix:
- Match Keys: Ensure the
secretOrPublicKeyused in your verification function matches exactly what was used for signing. - Check Algorithm Confusion: A dangerous vulnerability where a hacker changes the algorithm from
RS256toHS256. Read our deep dive on JWT Algorithm Confusion Security.
- Match Keys: Ensure the
3. JsonWebTokenError: jwt malformed
- Cause: The token string does not follow the standard
header.payload.signatureformat. It might be missing a period, contain non-Base64 characters, or be accidentally truncated. - Fix:
- Check for extra whitespace or newlines in the string.
- If sending via the
Authorization: Bearer <token>header, ensure the "Bearer" prefix is correctly stripped before passing the token to your library.
4. JsonWebTokenError: jwt not active (NotBeforeError)
- Cause: The
nbf(not before) claim timestamp is in the future. The token was issued but isn't allowed to be used yet. - Fix:
- Check server clock synchronization.
- If intentional (e.g., a scheduled access token), wait for the designated start time.
5. Error: invalid algorithm
- Cause: The algorithm specified in the JWT header (e.g.,
noneorHS256) is not in the list of algorithms the server is configured to accept. - Fix:
- Explicitly set the
algorithmsarray in your verification code (e.g.,jwt.verify(token, key, { algorithms: ['RS256'] })). This prevents "Algorithm Downgrade" attacks.
- Explicitly set the
How to Debug a JWT Without Exposing It
One of the most common mistakes developers make is pasting a production JWT into a public online decoder to see why it's failing.
The Risk: Most online decoders are marketing frontends for SaaS companies. When you paste your token, it is sent to their server. If that token is still valid, the tool provider (or anyone with access to their logs) can compromise your user sessions or administrative accounts.
The Solution: Local Browser Decoding
FmtDev provides a 100% Client-Side solution. Our tools run entirely in your browser's memory using JavaScript; your token never leaves your machine.
- Copy your problematic JWT.
- Navigate to our Local JWT Decoder.
- Paste the token to instantly see the decoded Header and Payload.
- Check the
exp,iat, andnbfclaims specifically—they are the most common culprits for "Expired" or "Not Active" errors.
JWT Expiration — How Token Lifetime Works
JWTs are "stateless," meaning the server doesn't need to look up a session in a database. Everything it needs to know is inside the token.
exp(Expiration Time): The Unix timestamp when the token must stop being accepted.iat(Issued At): When the token was originally generated.nbf(Not Before): The earliest possible time the token can be used.
Calculating Lifetime
You can calculate the remaining time by subtracting the current Unix timestamp (in seconds) from the exp value.
// Node.js example using jsonwebtoken
const jwt = require('jsonwebtoken');
try {
const decoded = jwt.verify(token, 'your-secret');
} catch (err) {
if (err.name === 'TokenExpiredError') {
const expiredAt = err.expiredAt;
console.error(`Token expired at: ${expiredAt}`);
}
}
Common Mistake: Lifetime Management
- Too Short: 1 minute. Users will experience constant 401 errors if the refresh logic isn't perfect.
- Too Long: 1 year. If a token is stolen, the attacker has access for the entire year unless you implement a complex blacklist/revocation system.
How to Prevent JWT Errors in Production
Prevention is better than debugging. Follow these industry standards to minimize JWT issues:
- Explicit Verification: Always pass the expected algorithm to the verify function. Never rely on the token header's suggestion.
- Use Asymmetric Keys: For larger systems, sign tokens with a private key (RS256) and verify them using a public key. This allows different microservices to verify tokens without knowing the secret signing key.
- Refresh Token Rotation: Issued short-lived access tokens (15 mins) and long-lived refresh tokens (7 days). Rotate the refresh token every time it is used to detect potential theft.
- Handle Clock Skew: Many libraries allow a
clockTolerance(e.g., 30 seconds) to account for minor time differences between servers. - Payload Privacy: Never put passwords, API keys, or PII in a JWT. It is encoded, not encrypted.
For a deeper dive into security, see our related post on Safe JWT Decoding Locally.
FAQ
Why does my JWT say "invalid signature"?
The most common cause is using the wrong secret key or public key for verification. Make sure the key used to verify matches exactly the key used to sign the token. Also, check that you aren't accidentally trying to verify an RS256 token with a HMAC secret.
How long should a JWT access token last?
For API access tokens, 15-30 minutes is standard. Use refresh tokens to get new access tokens without requiring the user to log in again. This limits the "blast radius" if a token is leaked.
Can I decode a JWT without the secret key?
Yes. The header and payload of a JWT are Base64 encoded, not encrypted. Anyone can decode and read them. The secret key is only needed to verify the signature to prove the token hasn't been tampered with.
Is it safe to paste my JWT into an online decoder?
No. Online decoders send your token to their server where it can be logged. Use a local decoder like FmtDev's JWT Decoder that runs in your browser with zero server calls.
Conclusion
Understanding "JWT Expired" and "Invalid Signature" errors is a rite of passage for modern developers. By implementing proper clock sync, explicit algorithm verification, and using local debugging tools, you can ensure your authentication flow is both robust and secure.