jwt debugging security authentication web-development

Solving 'JWT expired' and common JSON Web Token Errors

A comprehensive guide to fixing JWT errors like 'invalid signature', 'token expired', and 'malformed token'. Learn how to debug authentication issues in your app.

2026-04-11 Use This Tool

Solving "JWT expired" and common JSON Web Token Errors: A Complete Guide

JSON Web Tokens (JWT) are the industry standard for securely transmitting information between parties as a JSON object. They are widely used for authentication and authorization in modern web and mobile applications. However, because they are cryptographically signed and often have strict expiration rules, they can be a major source of debugging headaches.

In this guide, we will break down the most common JWT errors, explain why they happen, and show you how to fix them.


1. Common JWT Error Messages

Depending on the library you use (like jsonwebtoken in Node.js), you will encounter these common error names:

  • TokenExpiredError: The token is valid but has passed its expiration time.
  • JsonWebTokenError: invalid signature: The token's signature does not match the secret/key provided.
  • JsonWebTokenError: jwt malformed: The string provided is not a valid JWT structure.
  • JsonWebTokenError: jwt signature is required: A token was provided without a signature section.
  • JsonWebTokenError: jwt invalid audience: The aud claim in the token doesn't match the expected value.

2. Top Causes and Solutions

2.1 "TokenExpiredError" (JWT expired)

Every secure JWT should have an exp (expiration) claim. Once the current time passes this value, the token is no longer valid.

The Symptom: Users are suddenly logged out, or API requests start returning 401 Unauthorized errors with the message jwt expired.

The Solution:

  1. Refresh Tokens: Implement a "Refresh Token" strategy so users don't have to log in manually every time an access token expires.
  2. Clock Sync: Ensure your server's clock is synchronized using NTP. Even a few seconds of drift can cause issues.
  3. Check iat and nbf: Ensure the "issued at" (iat) and "not before" (nbf) claims are also correct.

2.2 "invalid signature"

A JWT consists of three parts: Header, Payload, and Signature. The signature is created by hashing the header and payload with a secret key. If even one character in the payload changes, or if the wrong secret key is used, the signature becomes invalid.

The Cause:

  • Using the wrong secret or public key to verify the token.
  • A mismatch between the algorithm used to sign (e.g., HS256) and verify (e.g., RS256).
  • The token was tampered with or corrupted during transmission.

The Solution:

  • Double-check your environment variables for the secret key.
  • Verify that the alg header in the JWT matches the algorithm you are using for verification.

2.3 "jwt malformed" or "jwt decode failed"

A valid JWT must have three parts separated by dots (header.payload.signature). If any part is missing or if the string is not valid Base64URL, it is considered malformed.

The Cause:

  • Passing a "Bearer " prefix string directly to the library (e.g., atob("Bearer <token>")).
  • Copy-pasting a partial token.
  • Extra whitespace or hidden characters in the token string.

The Solution: Ensure you are stripping the Bearer prefix before passing it to your decoder.

const token = authHeader.split(' ')[1]; // Extract token from "Bearer <token>"

2.4 "jwt invalid audience" or "jwt invalid issuer"

These errors occur when the aud (audience) or iss (issuer) claims in the payload don't match the values your server expects.

The Solution: Ensure the configuration on your authentication server (e.g., Auth0, Firebase, or your own) matches the verification options in your application code.


3. Advanced Troubleshooting

3.1 Inspecting the Payload

If you are getting a signature error, the first step is to inspect the payload to see if it contains the data you expect. You don't need the secret key to decode and read the payload (since it's just Base64 encoded).

3.2 Algorithm Confusion Attacks

Ensure your library is configured to only allow the specific algorithms you expect. Some older libraries were vulnerable to an attack where an attacker could change the header to alg: none, bypassing security. Modern libraries have mostly fixed this, but always explicitly define your allowed algorithms.

jwt.verify(token, secret, { algorithms: ['HS256'] });

4. Prevention and Best Practices

  1. Short-lived Access Tokens: Keep access tokens short-lived (e.g., 15 minutes) and use refresh tokens for longer sessions.
  2. Secure Secrets: Never hardcode your JWT secret. Use environment variables and rotate them periodically.
  3. Validate Every Request: Never trust a JWT without verifying its signature on the server side.
  4. Use HTTPS: Always transmit tokens over HTTPS to prevent intercepting "Man-in-the-Middle" attacks.

5. FAQ: Frequently Asked Questions

Q: Can I read the data inside a JWT without the secret?

A: Yes. The header and payload are only Base64URL encoded, not encrypted. Anyone who has the token can read the data. Never put sensitive information like passwords or credit card numbers in a JWT payload.

Q: What is the difference between HS256 and RS256?

A: HS256 uses a single secret key for both signing and verifying (symmetric). RS256 uses a private key to sign and a public key to verify (asymmetric), which is more secure for distributed systems.

Q: How do I handle a "jwt expired" error on the frontend?

A: Catch the 401 error in your API interceptor. If the error is "jwt expired", attempt to call your "refresh token" endpoint. If that fails, redirect the user to the login page.


6. Quick Check Tool

Having trouble with a specific token? Use our JWT Decoder & Debugger. It allows you to:

  • Instantly decode any JWT to see its Header and Payload.
  • Check expiration status and claims like iat, exp, and nbf.
  • Identify malformed tokens and encoding issues.
  • Validate signatures (if you provide your secret key locally).

Related Errors