Learn how JWT decoding works, what token claims mean, and how to debug authentication issues without leaking secrets.
JWTs are everywhere in modern authentication. They show up in API requests, browser storage, mobile apps, webhooks, service-to-service calls, and identity provider integrations. When auth breaks, decoding the token is often the fastest way to understand what is happening.
But there is an important distinction:
Decoding a JWT is not the same as verifying it.
A JWT Decoder helps you inspect the header and payload. It can show claims such as issuer, subject, audience, expiration, scopes, and custom fields. It does not prove the token is trustworthy unless the signature is verified with the correct key and algorithm.
Use decoding for debugging. Use verification for trust.
A JSON Web Token usually has three parts:
header.payload.signatureEach part is base64url-encoded. The header describes the token type and signing algorithm. The payload contains claims. The signature helps verify that the token was signed by the expected authority and has not been modified.
The payload might include:
iss: issuer.sub: subject, often the user ID.aud: audience.exp: expiration time.iat: issued-at time.nbf: not-before time.scope or permissions: allowed actions.Seeing these values makes many auth problems obvious.
The token is expired. Check exp. JWT timestamps are usually Unix timestamps in seconds, not milliseconds. Use a Unix Timestamp Converter if needed.
The audience is wrong. A token issued for one API may be rejected by another. Check aud.
The issuer does not match. Staging and production identity providers may have different issuer URLs. Check iss.
The user has the wrong role. Inspect role, scope, or permission claims.
The token is not active yet. Check nbf.
The frontend sends the wrong token. Decode the token being sent, not the token you think is being sent.
JWTs can be sensitive. A bearer token may grant access to an account or API. Treat it like a password while it is valid.
Safer habits:
If a token grants access, assume anyone who sees it can use it until it expires or is revoked.
Because JWT header and payload are just encoded JSON, anyone can decode them. Anyone can also create a fake JWT payload.
For example, a malicious user could change:
{
"role": "user"
}to:
{
"role": "admin"
}The changed token should fail signature verification. If your backend trusts decoded payloads without verifying signatures, that is a serious security bug.
Your server must verify:
Never trust a token because it "looks right."
JWT verification must restrict allowed algorithms. Do not blindly accept whatever algorithm the token header says.
Dangerous patterns include:
none algorithm.Modern libraries usually help prevent these mistakes, but configuration still matters.
JWT bugs are not only about token content. They also come from where tokens are stored and how they are sent.
Check:
Authorization header?Bearer prefix?HttpOnly, Secure, and SameSite where appropriate?Authentication failures often come from missing prefixes, stale storage, wrong cookie domains, or mixed environments.
exp, iss, aud, sub, and scopes.This workflow avoids guessing and keeps the investigation tied to the real request.
Using decode as authorization. Decoding is inspection. Verification is security.
Ignoring expiration units. Seconds and milliseconds are easy to confuse.
Logging full tokens. Logs live longer than requests.
Mixing refresh and access tokens. Refresh tokens deserve stronger protection.
Putting too much data in the payload. JWT payloads are readable by clients. Do not store secrets there.
A JWT decoder is an excellent debugging tool. It helps you see why a token is accepted, rejected, expired, mis-scoped, or meant for the wrong audience.
Just keep the boundary clear. Decode to inspect. Verify to trust. Redact before sharing. Rotate anything exposed.