Skip to main content

How to Debug JWT Authentication Errors Using a Token Decoder

Terminal screen displaying decoded JSON token output
Try the Tool
JWT Decoder
Decode, inspect, and validate JSON Web Tokens instantly.

A 401 response tells you that authentication failed. It rarely tells you why. When your application uses JSON Web Tokens, the actual cause is almost always sitting inside the token itself, in a claim value or algorithm field that is invisible until you decode the token.

JWT authentication errors fall into a small, predictable set of categories: the token expired, the signature does not match, the issuer or audience is wrong, or the structure is malformed. Each of these leaves a fingerprint in the token's header or payload. A decoder surfaces those fingerprints in seconds. Trying to diagnose from error log text alone does not.

This guide covers the common JWT error patterns, how to read a decoded token to find the root cause, and how to make JWT debugging fast and systematic rather than trial-and-error.

What JWT Authentication Errors Look Like in the Wild

JWT errors typically surface as HTTP 401 or 403 responses, but the message bodies vary by framework and implementation. Common messages include:

  • Token has expired
  • Invalid signature
  • jwt malformed
  • JsonWebTokenError: invalid algorithm
  • NotBeforeError: jwt not active
  • Unauthorized: audience mismatch
  • invalid_token: The access token provided has expired

The problem with relying on these messages alone is that they describe the outcome, not the cause. "Invalid signature" could mean the signing key changed between environments, the algorithm in the header does not match what the server expects, or the token was modified in transit. You need to look at the token to know which.

This is especially true when working across multiple services or environments, where a token issued in staging might arrive at a production endpoint with different validation rules, or where a recently rotated key creates a window of failures for tokens issued before the rotation.

The Three Parts of Every JWT

A JWT has three base64url-encoded sections separated by dots: header, payload, and signature.

The header declares the signing algorithm (alg) and the token type (typ). Common algorithm values are HS256 for HMAC with SHA-256, RS256 for RSA with SHA-256, and ES256 for ECDSA. The algorithm in the token header must match what the receiving server is configured to accept. Sending an HS256-signed token to a service that only trusts RS256 produces a signature failure, even if the key itself is correct.

The payload contains claims, structured key-value pairs describing the token's subject, scope, and validity window. Standard registered claims include:

  • iss (issuer): the authority that issued the token
  • sub (subject): the entity the token represents, typically a user ID
  • exp (expiration time): Unix timestamp when the token becomes invalid
  • iat (issued at): when the token was created
  • aud (audience): which service or resource the token is intended for
  • nbf (not before): earliest time the token is valid

Private claims, including application-specific fields like role, scope, or tenant_id, sit alongside these standard fields in the same payload object.

The signature is a cryptographic hash of the encoded header and payload, computed using the signing key. If any part of the header or payload is modified after signing, the signature becomes invalid. The signature is what makes the token tamper-evident, but only if the server verifies it with the correct key.

Server rack cables and network connections Photo by Eric Stoynov on Unsplash

How to Use a JWT Decoder to Find the Problem

Paste the raw token into the JWT Decoder at EvvyTools. The tool splits the three sections and displays each as readable JSON, with an expiry countdown, claim explanations, and signature verification shown together.

Work through these checks in order:

Check the expiry claim (exp) first. Convert the value to a human-readable timestamp. If it is in the past, the token is expired. Expired tokens are the most common JWT error by volume. The expiry countdown removes the need to convert Unix timestamps manually.

Check the issuer (iss) next. Compare it against the value your server expects. Mismatches happen when tokens from a development identity provider reach a production API, or when a third-party auth service updates its issuer URL without a corresponding configuration update on the receiving side.

Check the audience (aud). If your API validates this claim, the value in the token must match the expected audience string exactly, including case. This claim is easy to overlook during initial development, especially when a single identity provider serves multiple services with different audience values.

Check the algorithm (alg). A token with alg: none is unsigned and must always be rejected. Beyond the obvious case, algorithm confusion is a real attack class: if an API accepts whatever algorithm the token declares rather than enforcing a specific algorithm, a crafted token can bypass signature verification. RFC 7519 requires that servers validate the algorithm explicitly.

Run signature verification. Provide the public key or shared secret in the decoder's verification field. If verification fails with what you believe is the correct key, the token was signed with a different key, or the header or payload was modified after signing.

Network operations center with multiple monitors Photo by Samon Yu on Pexels

Six JWT Errors and Their Root Causes

Expired token (exp in the past): Issue a new token via the refresh endpoint. If this happens frequently in production, check whether the client-side token refresh logic is firing correctly before expiry, not after.

Invalid signature: The most ambiguous error. Work through the possibilities: wrong key (environment mismatch after a deploy), wrong algorithm (header says RS256, server configured for HS256), token modified in transit (check for proxy interference or logging middleware that alters the Authorization header). Signature verification in the decoder will confirm which key the token was signed with.

Issuer mismatch (iss): Happens when tokens cross environment boundaries or when a multi-tenant system routes a token from one tenant's identity provider to another tenant's API. Always validate iss server-side and reject tokens from unexpected issuers.

Audience mismatch (aud): The token was issued for a different service. Confirm that the client is requesting tokens with the correct audience parameter, and that the receiving API is validating aud rather than ignoring it.

Malformed token: The base64url encoding is broken, or the dot-delimited three-part structure is missing. Common causes: the client strips the Bearer prefix incorrectly, a logging pipeline double-encodes the value, or URL encoding corrupts the token's + and / characters when it passes through a query string.

Not before violation (nbf): The nbf claim sets the earliest time a token is valid. If services have minor clock skew and a token arrives at a service whose clock is behind the issuer's clock, the receiving server may reject a freshly issued token as not yet active. The timeline view in the JWT Decoder shows iat, nbf, and exp together, making clock-skew issues visible immediately.

"One of the most common JWT debugging mistakes is reading the error message alone without looking at the actual token claims. A decoder that shows expiry, issuer, and signature verification together in one view cuts debugging from several round-trips down to a single check." - Dennis Traina, founder of 137Foundry

Why Client-Side Decoding Is Useful but Not Sufficient

Base64url-decoding the header and payload works without a key; the payload is signed, not encrypted, so anyone can read the claims. This is useful for confirming what a token contains, but it does not tell you whether the token is authentic.

Signature verification requires the matching key: the shared secret for HMAC algorithms, or the public key for RSA and ECDSA. Without verification, a modified or entirely fabricated token appears identical to a legitimate one.

The OWASP Web Security Testing Guide covers JWT-specific security testing, including algorithm confusion attacks and the alg: none bypass. Auth0 publishes detailed documentation on implementing each validation step correctly across common frameworks and languages.

On the transport side, the MDN Authorization header reference documents the exact format for sending bearer tokens, and a small formatting mistake here can corrupt the token before it reaches your validation logic.

A Step-by-Step JWT Debugging Workflow

When a JWT error appears in your logs, work through this sequence rather than guessing:

  1. Extract the full token from the Authorization header (strip the Bearer prefix before pasting).
  2. Paste the token into the JWT Decoder. Note the expiry status and algorithm immediately.
  3. Compare iss, aud, and exp against your API's expected values. These three claims account for most real-world JWT failures.
  4. If claims look correct, run signature verification with the expected key. Failure here means a key mismatch or a tampered token.
  5. If you see intermittent failures, check whether nbf is close to iat and whether services have synchronized clocks. A few seconds of skew causes failures that do not reproduce reliably.
  6. Use the token comparison view when debugging across environments: paste a working token from staging alongside a failing token from production to spot the difference directly.

Log the decoded claims (not the raw token) when a JWT fails. Structured claim logging means you can reconstruct the failure scenario later without needing to capture another token.

Chalkboard with handwritten mathematical formulas Photo by Bernice Chan on Pexels

Token Comparison and Environment Differences

One underused feature in JWT debugging is token comparison. When a token works in one environment but fails in another, the difference is almost always in the claims or the signing key, not in your code. Comparing the decoded output of a working token against a failing token makes the difference obvious.

Common environment differences that surface through comparison:

  • The iss value uses the staging URL in a token that reached the production validator
  • The aud is correct for the API gateway but wrong for a downstream microservice doing its own validation
  • The exp window is shorter in production than in development, causing refresh timing to fail
  • The algorithm is HS256 in development and RS256 in production, requiring different key handling

The EvvyTools tools directory includes additional developer tools for HTTP headers, DNS, encoding, and schema validation that come up alongside authentication debugging. For background on related security topics, the EvvyTools blog covers HTTP security headers, encoding formats, and DNS diagnostics that often intersect with JWT and API authentication work.

Making JWT Debugging Systematic

JWT authentication errors are predictable once you know the anatomy. The error message tells you there is a problem. The token tells you what the problem is. Decoding the header and payload takes seconds and narrows the cause to a specific claim, algorithm, or key.

Build JWT decoding into your debugging workflow from the start rather than as a last resort. The expiry countdown, claim display, and signature verification in the JWT Decoder give you everything you need to move from a vague 401 response to a specific root cause in under a minute.

Honey-Do Tracker — home maintenance for landlords and property managers
Share: X Facebook LinkedIn
Honey-Do Tracker — home maintenance for landlords and property managers