Try the JWT Decoder

JWT Decoder β€” Debug Authentication Errors by Inspecting Token Claims

Learn how to use a JWT decoder to debug 401 errors, understand the header, payload, and signature sections, check expiry and audience claims, and identify security issues like alg:none attacks.

By sadiqbd Β· June 7, 2026

JWT Decoder β€” Debug Authentication Errors by Inspecting Token Claims

A 401 error doesn't always mean the token is wrong β€” sometimes it means you're reading the wrong token

An API returns 401 Unauthorized. The developer checks the code β€” the token is being sent. They check the expiry β€” it looks fine in the logs. They spend 45 minutes debugging before realising: the token they're checking in the logs is a different token from what's actually being sent to that endpoint. A JWT decoder would have resolved this in 30 seconds.

JWT debugging is about seeing what's actually in the token versus what you think is in the token. The decoder closes that gap.


What Every JWT Contains

A JWT has three Base64URL-encoded sections separated by dots:

[header].[payload].[signature]

The header

Always tells you the algorithm and token type:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "key-id-2024-06"
}
  • alg: The signing algorithm. HS256 = HMAC-SHA256 (symmetric, shared secret). RS256 = RSA-SHA256 (asymmetric, public/private key pair). ES256 = ECDSA (more compact than RSA).
  • typ: Almost always "JWT"
  • kid: Key ID β€” which specific key was used to sign this token. Relevant when a service rotates keys.

The payload (claims)

Contains the actual information about the user and token:

{
  "iss": "https://auth.example.com",
  "sub": "user_42",
  "aud": ["api.example.com", "admin.example.com"],
  "exp": 1718003600,
  "iat": 1718000000,
  "nbf": 1718000000,
  "jti": "abc123-unique-id",
  "email": "user@example.com",
  "roles": ["admin", "editor"],
  "tenant_id": "org_789"
}

The standard claims:

  • iss (issuer): Who created the token
  • sub (subject): The user or entity the token is about
  • aud (audience): Who the token is intended for β€” an API should reject tokens with a non-matching audience
  • exp (expiration): Unix timestamp β€” token is invalid after this
  • iat (issued at): When the token was created
  • nbf (not before): Token is invalid before this timestamp
  • jti (JWT ID): Unique identifier for this specific token

Custom claims (email, roles, tenant_id) are application-specific additions.

The signature

Computed from the header + payload + secret/private key. Cannot be decoded without the secret. The decoder shows the raw signature bytes but cannot verify or reverse them without the signing key.


How to Use the JWT Decoder on sadiqbd.com

  1. Paste the JWT β€” the complete token string (all three sections including dots)
  2. Decode β€” header, payload, and signature are shown separately
  3. Check expiry β€” the tool converts exp to a readable date and shows whether it's expired
  4. Review claims β€” confirm audience, roles, user ID, and any custom claims

Debugging Authentication Problems with JWT Decoder

Problem: 401 on a valid-looking token

Decode the token being sent. Check:

  1. Is exp in the past? The most common cause. The decoder shows the expiry time in human-readable form β€” exp: 1718003600 β†’ June 10, 2024 at 11:13 AM UTC. If current time is past this, the token is expired.

  2. Does aud match the API? If the token has "aud": "payments.example.com" but you're calling users.example.com, the users API should (and often does) reject the token. Check what audience your API requires.

  3. Is iss correct? Some APIs validate the issuer. A token from a staging environment sent to production will fail if the issuers differ.

  4. Are required custom claims present? Your API may require tenant_id or specific roles. Check whether they're in the payload.

Problem: User can't access an admin page despite being an admin

Decode the token actually being used (from the request headers in the browser's Network tab). Check the roles claim. If "roles": ["viewer"] instead of "roles": ["admin"], the token was issued before the role was updated. The user needs to log out and back in to get a new token with the updated role.

Problem: Suspicious-looking JWT

A token header shows "alg": "none". This is a known vulnerability in some JWT libraries β€” the none algorithm means no signature verification. If your system accepts this, it means any payload would be accepted without verification. This is a critical security issue.

Another red flag: "alg": "HS256" when you expect "alg": "RS256". An attacker might be trying an algorithm confusion attack β€” sending an RS256-signed token but claiming HS256 (which would make the library try to verify using the public key as an HMAC secret, potentially succeeding if the library is vulnerable).


JWT Expiry and Token Lifecycle

Understanding token lifecycle is essential for understanding JWT-related errors:

Short-lived access token (5 min – 1 hour): The token you send to APIs. Short expiry limits damage if compromised.

Refresh token (days to weeks): A long-lived token used to get new access tokens without re-authentication. Usually stored more securely (HttpOnly cookie vs. localStorage).

Token rotation: When a refresh token is used, a new refresh token is issued and the old one is invalidated. This prevents infinite token reuse.

The JWT decoder shows access token lifetime (from iat to exp). If the expiry is 1 year, the access token has a security problem β€” it should be much shorter.


What the Decoder Cannot Tell You

Whether the signature is valid. Verifying the signature requires the signing key β€” which only the server that issued the token has. The decoder shows the claims; it cannot confirm whether the token is genuine without the key.

Whether the token has been revoked. JWTs are stateless β€” once issued, they're valid until expiry unless you maintain a token blocklist. The decoder shows the claims but not whether the issuer has invalidated the specific token.

Whether the custom claims are accurate. If a token says "role": "admin", that's what the issuing system said at issue time. Whether it's still true (maybe the admin status was revoked) depends on whether the system re-validates claims on each request.


Security Reminders

Production tokens are sensitive. A valid, unexpired JWT for your production system should be treated like a password. Don't paste it into tools you don't trust. For debugging production issues, use tokens that will expire quickly or have already expired.

The decoder confirms what you think is there. The primary use case is verifying that the token contains the expected claims β€” not necessarily breaking security, but ensuring your application logic is working as intended.


Frequently Asked Questions

Can I use the decoder to modify a JWT and make it work differently? No β€” modifying the payload would invalidate the signature. Unless you have the signing secret, you can't create a valid modified JWT.

What if the JWT has no expiry (exp claim)? Tokens without expiry are problematic β€” they're valid indefinitely unless explicitly revoked. Well-designed systems always include expiry. A missing exp in a production token should be flagged as an implementation issue.

Why are some JWT payloads larger than others? More claims = larger payload. Some systems embed extensive user profile data in the JWT to avoid database lookups. This is a trade-off between token size and authentication performance.

Is the JWT Decoder free? Yes β€” completely free, no sign-up required.


JWT debugging without a decoder is guesswork. With a decoder, the problem is almost always visible within 30 seconds of pasting the token. For any authentication issue involving JWTs, it's the first tool to reach for.

Try the JWT Decoder free at sadiqbd.com β€” paste any JWT and inspect its header, payload, and expiry instantly.

Try the related tool:
Open JWT Decoder

More JWT Decoder articles