A JSON Web Token often looks like opaque security data, but its header and
payload are normally readable Base64URL segments. That makes local inspection
straightforward. It also creates two common mistakes:
- Uploading a live bearer token to an unknown server-side decoder.
- Treating decoded claims as proof that the token is authentic.
This workflow separates three different jobs:
- Inspecting the token structure.
- Checking claims such as issuer, audience and expiration.
- Verifying that a trusted issuer signed the token.
The first two can be done locally in a browser tab. The third requires the
expected algorithm and trusted key material.
1. Treat the JWT as a credential
A JWT may be readable, but it can still grant access to an API. If it is a
bearer token, anyone who receives the original compact token may be able to use
it until it expires or is revoked.
Before debugging, decide what kind of token you are handling:
- A fake or test token is usually safe to paste into examples.
- A staging token may still expose internal systems.
- A production token should not be copied into public tools, tickets or chat.
If a production token has already crossed an untrusted boundary, redaction is
not enough. Rotate or revoke it and treat the event as a credential exposure.
2. Split the compact token
A typical JWT has three dot-separated segments:
header.payload.signature
The header and payload are Base64URL-encoded JSON. They are not encrypted by
default. That means you can decode the first two segments locally and read the
claims without sending the compact token to a server.
The header usually includes fields such as:
{
"alg": "RS256",
"typ": "JWT",
"kid": "example-key-id"
}
The payload may include registered claims:
{
"iss": "https://issuer.example",
"aud": "api.example",
"sub": "user_123",
"exp": 1764211200,
"nbf": 1764207600,
"iat": 1764207600,
"scope": "read:profile"
}
Do not paste a real token into an article, issue or support ticket. Use a
synthetic example or share only the claim values needed to explain the failure.
3. Check the claims that commonly fail
Most authentication debugging starts with a small set of fields.
iss
The issuer must match the identity provider or token service expected by the
API. A common failure is using a token from the right environment but the wrong
issuer configuration.
aud
The audience should identify the API or client that the token was issued for.
If the token was minted for a different API, the claims may look correct while
the request still fails authorization.
exp, nbf and iat
JWT numeric date fields are seconds since the Unix epoch. Many bugs come from
mixing seconds and milliseconds.
Check:
- Is
expalready in the past? - Is
nbfstill in the future? - Does
iatmake sense for the login or refresh event? - Are the server and client clocks skewed?
Custom roles and scopes
Applications often encode permissions in custom claims such as scope,
roles, permissions or tenant-specific fields. These are useful for
debugging, but they are only trustworthy after signature verification.
4. Decoding is not verification
Anyone can construct a JWT-looking string with a header and payload. A decoder
can tell you what the token claims. It cannot tell you whether the token was
signed by the expected issuer.
Verification needs:
- The expected algorithm.
- The trusted signing secret or public key.
- Issuer and audience checks.
- Rejection of unexpected algorithms.
- Current time validation for
expandnbf.
For HS256 development tokens, the verifier needs the shared secret. For RS256,
ES256 or production identity providers, the backend normally verifies against a
published JWKS or a configured public key.
Do not trust the alg value from the token by itself. Your verification code
should enforce the algorithm that the application expects.
5. Build a share-safe diagnostic
The useful output of JWT debugging is usually not the original token. It is a
small set of facts:
Token structure: 3 JWT segments
Header alg: RS256
Header kid: example-key-id
Issuer: https://issuer.example
Audience: api.example
Subject: user_123
exp: 1764211200 / 2025-11-27T00:00:00Z
nbf: 1764207600 / 2025-11-26T23:00:00Z
Verification error: audience mismatch
Before sharing the diagnostic:
- Remove the original compact token.
- Remove unrelated cookies or authorization headers.
- Scan the remaining text for other credentials.
- Include the exact verification error and expected issuer or audience.
That gives the next person enough context to debug without receiving a reusable
credential.
6. A local workflow
My preferred workflow is:
- Decode the JWT header and payload locally.
- Convert
exp,nbfandiatto readable dates. - Compare
issandaudwith the API configuration. - Verify the signature in backend code or a local lab with trusted key material.
- Redact the original token before opening a ticket or asking for help.
I maintain MonoTools, including a browser-local JWT decoder and the longer
canonical guide for this workflow:
Disclosure: MonoTools is my project. The guide and decoder are useful for local
inspection, but signature verification still belongs in trusted verification
code with the expected key material.
Top comments (0)