JWT debugging becomes much easier when you separate three different tasks: decoding a token, checking its claims, and verifying its signature. This guide provides a reusable workflow for inspecting JSON Web Tokens, diagnosing validation failures, testing tokens safely, and deciding when a problem belongs to the client, API, identity provider, key configuration, or system clock.
Overview
A JSON Web Token, or JWT, is commonly used to carry authentication and authorization data between systems. A compact JWT usually has three dot-separated parts: a header, a payload, and a signature. The header identifies the token type and signing algorithm; the payload contains claims; and the signature helps a verifier detect whether the signed contents have been altered.
Decoding a JWT only means converting its encoded header and payload into readable JSON. It does not prove that the token is authentic, current, or intended for your application. Verification requires a trusted key, an allowed algorithm, and validation rules that match the API or identity provider's configuration. Treat every decoded value as untrusted until those checks pass.
For local troubleshooting, a JWT decoder online or a command-line utility can make the structure visible. Use test tokens whenever possible. Never paste production access tokens, refresh tokens, session credentials, or other secrets into an unfamiliar website or shared debugging tool. A local decoder is preferable when the token contains sensitive information.
JWT claims explained
| Item | What to inspect | Typical debugging question |
|---|---|---|
alg | The signing algorithm named in the header | Does it match the verifier's allowed algorithm? |
kid | The key identifier, when present | Can the verifier locate the corresponding public key? |
iss | The token issuer | Is this the expected identity provider or authorization server? |
aud | The intended audience | Does it identify this API or application? |
exp | Expiration time | Has the token expired according to the verifier's clock? |
nbf | Not-before time, when present | Is the token being used before it becomes valid? |
iat | Issued-at time | Was it issued when expected, or is there a clock or environment problem? |
sub | Subject identifier | Does the subject map to the expected user or service? |
scope or roles | Application permissions | Does the token grant the operation being attempted? |
Claim names are not automatically universal application rules. Some are registered conventions, while others are private claims defined by a specific system. Confirm how your API interprets them rather than assuming that a readable claim grants access.
Checklist by scenario
When you need to read a token
- Confirm that the value has the expected dot-separated structure. A standard signed JWT commonly has three segments, although encrypted or otherwise specialized token formats may differ.
- Decode the header and payload without treating either as proof of authenticity.
- Record the algorithm, key identifier, issuer, audience, subject, expiration, not-before time, and permissions.
- Convert numeric date values using a reliable tool and check the timezone and units. JWT time claims are commonly represented as numeric timestamps, but your application should follow the behavior of its JWT library.
- Remove the token from logs, screenshots, browser history, issue trackers, and chat messages after debugging.
When an API returns an expired-token error
- Inspect
expand compare it with the current time on the verifying server, not only the developer workstation. - Check whether the token is cached by a browser, API client, proxy, or application process.
- Confirm that the client sends the newly issued token and uses the expected authorization scheme and header format.
- Check refresh-token handling separately. A refresh-token failure is not always fixed by retrying the access-token request.
- Verify that the server's clock is synchronized. Small clock differences can make a token appear expired or not yet valid.
When the issuer or audience fails
- Compare the token's
issvalue with the exact issuer configured by the API, including scheme, hostname, path, and trailing-slash behavior where relevant. - Compare
audwith the API's configured audience. Do not assume that a token issued for one service is valid for every service in the same organization. - Check the environment. Development, staging, and production commonly use different issuers, audiences, client identifiers, and signing keys.
- Confirm that the client requested the token for the correct resource or API rather than merely obtaining a token from a trusted provider.
When signature verification fails
- Identify the algorithm in the header and compare it with the algorithms explicitly permitted by the verifier.
- If the token includes
kid, confirm that the key set used by the API contains that identifier. - Check whether the identity provider recently rotated keys and whether the API has refreshed its key set.
- Confirm that the verifier is using the correct key type. Symmetric signing uses a shared secret; asymmetric signing uses a private key to sign and a corresponding public key to verify.
- Make sure no middleware, proxy, URL decoder, newline conversion, or storage layer changed the token before verification.
Do not solve a signature error by disabling verification or accepting any algorithm supplied by the token. If you are testing a library, configure a deliberately limited algorithm allowlist and use a non-production key.
When a token is valid but access is denied
A valid signature does not guarantee authorization. Check whether the endpoint requires a particular scope, role, tenant, subject, or permission claim. Then compare the token's claims with the API's authorization rule and the account or service being used. A successful authentication step can be followed by a legitimate authorization failure.
What to double-check
Use a structured validation order
A practical order is: parse the token, verify the signature, validate the algorithm, validate time-based claims, validate issuer, validate audience, then apply application-specific authorization. Libraries may perform these checks in a different internal order, but your diagnostic notes should identify each result separately. This prevents a vague “JWT invalid” message from hiding the actual cause.
Separate client and server evidence
Capture the request environment without exposing the credential: endpoint, HTTP method, response status, relevant request identifier, token issue time, and a redacted claim summary. On the server, review the validation error category, configured issuer and audience, key identifier, key-set refresh state, and server time. Comparing these two views often reveals that the client is sending an old token or the server is using the wrong environment configuration.
Allow only intentional clock tolerance
Clock skew can occur between systems, so some JWT libraries support a small configured tolerance. Treat that setting as a controlled compatibility measure, not a replacement for time synchronization. Excessive tolerance can extend the practical lifetime of tokens or hide deployment problems. Document the value and test behavior around expiration and not-before boundaries.
Test the negative cases
A useful JWT token testing plan includes an expired token, a token with a future nbf, the wrong audience, the wrong issuer, a changed payload, an unknown key identifier, a disallowed algorithm, missing required claims, and insufficient permissions. Each case should produce the expected failure category without revealing sensitive token contents in logs.
For related operational work, keep authentication testing in the same change process as other deployment checks. A documented website launch checklist can help place API configuration, secrets, and post-launch verification alongside broader site QA.
Common mistakes
- Confusing decoding with verification: Anyone can often read an encoded payload. Readability is not authenticity.
- Trusting claims before validating the signature: Do not make authorization decisions from an unverified payload.
- Accepting the token's algorithm automatically: The application should define which algorithms and key types are allowed.
- Checking only expiration: A current token can still have the wrong issuer, audience, key, subject, or permissions.
- Using a production token in an online tool: Redact or replace sensitive credentials and prefer local tooling.
- Logging complete Authorization headers: Log a request identifier and safe metadata instead of the credential itself.
- Refreshing keys on every failure: Key refresh behavior should be bounded and deliberate; otherwise a bad token or network problem can create unnecessary load.
- Assuming every JWT has the same claims: Required claims and permission formats depend on the issuer and application contract.
- Fixing an environment mismatch in code: First compare configuration for the client, API, issuer, audience, and key set across environments.
When to revisit
Use this checklist whenever a new API integration is introduced, authentication behavior changes, a signing key is rotated, an identity provider configuration changes, or a service moves between environments. Revisit it before a deployment that changes token libraries, middleware, audience values, issuer URLs, permission mappings, or clock and infrastructure settings.
It is also worth reviewing after a recurring authentication incident. Record the original symptom, the claim or configuration that caused it, the validation result, and the test that prevents recurrence. Update examples when your JWT library changes its defaults, error handling, key discovery behavior, or time validation rules. Tooling can change too, so periodically confirm that any decoder, API client, test fixture, or browser extension used by the team handles tokens as expected and does not expose them.
A final five-minute workflow
- Use a safe, non-production token and decode its header and payload locally.
- Write down the expected issuer, audience, algorithm, key identifier, and time window.
- Verify the signature with the correct trusted key and an explicit algorithm allowlist.
- Check
exp,nbf, and clock tolerance on the verifying system. - Check application permissions, then test one valid case and the relevant failure cases.
This sequence keeps JWT debugging evidence-based: first establish what the token says, then whether it can be trusted, then whether it is valid for this service, and finally whether it is authorized for the requested action.