A JWT decoder can quickly reveal why an API request is failing, but decoding only makes a token readable; it does not prove that the token is authentic or acceptable. This guide explains how to inspect JWT headers and claims, check expiration and issuer values, compare tokens during debugging, and use browser-based tools without exposing production credentials.
Overview
JSON Web Tokens (JWTs) are compact strings commonly used to carry claims between an identity provider, an application, and an API. A typical token has three dot-separated sections:
header.payload.signature
The header describes how the token is intended to be processed. The payload contains claims, such as the subject, issuer, audience, and expiration time. The signature is generated from the encoded header and payload, using a signing method and key configured by the issuer.
A JWT decoder or a local decoding library can Base64URL-decode the first two sections so you can read them as JSON. That operation does not verify the signature, confirm the signing key, or establish that the token should be accepted by your application. Treat decoded output as untrusted input until verification and application-specific validation have completed.
This distinction is central to JWT debugging. If a token contains an unexpected role, audience, or expiration value, decoding can help you find the configuration problem. If the token appears correct, you still need a verifier to check its signature and validation rules. A readable token is not necessarily a valid token.
When working with an API response, a JSON formatter and validator can make nested claims easier to inspect after decoding. Keep the JWT workflow focused on diagnosis rather than treating an online tool as an authentication authority.
What to track
1. Token structure and formatting
Start by confirming that the value looks like a JWT: it normally contains three non-empty, dot-separated segments. Copying errors, surrounding quotation marks, a Bearer prefix, line breaks, or URL encoding can make a valid token appear malformed. Remove only transport-specific formatting before inspection, and do not alter the token when testing the actual request.
A decoder may show a header and payload even when the signature is invalid. Record whether the original token was copied from an authorization header, a cookie, local storage, or an identity-provider response. The source often explains differences between two apparently similar tokens.
2. Header fields
Pay particular attention to:
alg: the signing algorithm identifier. It should match the algorithms your verifier is explicitly configured to accept.kid: an optional key identifier used to select a verification key when an issuer rotates or maintains multiple keys.typ: an optional type indicator. Applications should not rely on it alone to determine whether a token is acceptable.
Do not change the algorithm setting in a decoder or verifier merely to make a failing token pass. Algorithm selection belongs in trusted server configuration, not in values supplied by an untrusted token.
3. Registered and application claims
JWT claims are JSON properties. Some commonly used registered claims include:
| Claim | Meaning | Debugging question |
|---|---|---|
iss | Issuer of the token | Does it match the identity provider or issuer configured for this environment? |
sub | Subject identified by the token | Does it identify the expected user, account, or service? |
aud | Intended audience | Does it contain the API or client identifier that is validating it? |
exp | Expiration time | Has the token expired according to the validating system's clock? |
nbf | Not-before time | Is the token being used before it becomes valid? |
iat | Issued-at time | When was it created, and does that fit the login or refresh event? |
jti | Token identifier | Can logs or revocation records identify this individual token? |
Applications may also add roles, permissions, scopes, tenant identifiers, or feature claims. Their names and meanings are application-specific. Compare them with the authorization code that consumes them rather than assuming that a claim named role or admin has a universal meaning.
4. Time values and clock differences
JWT time claims are commonly represented as numeric timestamps rather than human-readable dates. Convert them consistently when checking expiration, and note whether your tooling displays seconds or another unit. A token can be rejected because it is expired, not yet valid, or outside an allowed clock-skew window. Compare the issuer, application server, and local debugging machine carefully; a time-zone display difference is not necessarily a timestamp difference.
5. Verification results
Separate the inspection record from the verification record. A useful debugging note might state: “Payload contains the expected audience; local signature verification failed because the configured key set does not contain the header's key identifier.” That is more actionable than saying the decoder marked the token as valid.
Cadence and checkpoints
JWT debugging is usually triggered by a failed request, but a small recurring review can catch configuration drift before it becomes a production incident. Use a monthly or quarterly checkpoint for applications with changing identity providers, rotating keys, multiple environments, or regularly updated authorization rules.
At each checkpoint
- Review issuer configuration. Confirm that development, staging, and production use the intended issuer and discovery or key endpoints.
- Review audience expectations. Compare the audience accepted by each API with the audience emitted for each client or service.
- Test expiration handling. Use a non-production account and controlled short-lived tokens to confirm that expired and not-yet-valid tokens are rejected as expected.
- Check algorithm and key configuration. Ensure verifiers allow only the algorithms and key sources approved by the application design.
- Compare representative claims. Check scopes, roles, tenant values, and subject formats against the authorization logic and recent account changes.
- Review logs without collecting secrets. Prefer request IDs, issuer values, key identifiers, and failure categories over full token strings.
Keep a sanitized test token or a documented claim fixture for repeatable checks. Never use a live production access token as a permanent test artifact. If you need to inspect structured API errors alongside token claims, the JSON formatter guide provides a separate workflow for validating and organizing response data.
How to interpret changes
When a token stops working, compare a failing token with a recently successful token from the same environment. Look for one change at a time:
isschanged: the client may be pointed at a different tenant, realm, or environment.audchanged: the token may be intended for another API or client.expornbfchanged: investigate token lifetime, refresh behavior, and server clock alignment.kidchanged: the verifier may need access to a newly published key, or the wrong key set may be configured.- roles or scopes changed: the identity may have different permissions, or the API may be reading a different claim than the issuer provides.
- signature verification changed while claims look similar: check key retrieval, algorithm allowlists, token truncation, and the exact bytes sent over the request.
Do not diagnose authorization from the payload alone. A malicious party can create a token-shaped string with an elevated role or a future expiration date. The server must verify the signature and then apply issuer, audience, time, scope, and authorization checks according to its own policy.
Use browser-based developer tools only with synthetic, expired, revoked, or otherwise non-sensitive tokens. A third-party JWT decoder receives whatever you paste into it, and a token can grant access even when its payload does not contain an obvious password. For sensitive investigations, decode locally with your framework's library or a small offline script, and remove tokens from clipboard history, screenshots, tickets, and chat transcripts.
When to revisit
Revisit this JWT debugging checklist monthly or quarterly when authentication is business-critical, and immediately after an identity-provider migration, key rotation, framework upgrade, audience change, authorization redesign, or deployment across a new environment. The article is also worth revisiting whenever a login works in one environment but API calls fail in another.
Before closing an incident, record the symptom, environment, issuer, audience, key identifier, relevant time claims, verification result, and the corrective configuration change—without storing the complete token. Then run one controlled request using a fresh test token and one request using an intentionally expired or otherwise invalid token. Confirm that the first is accepted and the second is rejected for the expected reason.
For ongoing maintenance, keep a short token-debugging checklist beside your authentication tests:
- Separate the
Bearertransport value from the JWT before decoding. - Inspect header and payload structure, but treat both as untrusted.
- Check
iss,aud,exp,nbf, scopes, and roles. - Verify the signature with trusted configuration and the expected key.
- Test authorization separately from authentication.
- Use sanitized tokens and remove sensitive artifacts after debugging.
This routine keeps a JWT decoder in its proper role: a convenient inspection tool for understanding token contents, not a replacement for cryptographic verification or server-side security controls.