Decode JWTs locally with the JWT Decoder. Paste the token, read the claims, and nothing is uploaded.
Why tokens end up in error logs
The stack trace says 401, the request headers were logged for debugging, and there it is: a complete JWT in the log output, often from a test run or a misbehaving client.
That token is not just noise. It contains claims - subject, issuer, audience, expiry - that tell you exactly why authentication failed, provided you can read them.
The problem is how you read them. Pasting a token into a random online decoder sends it to that site's server, where it may be logged, stored, or replayed. A JWT is bearer credentials in many setups; treat it as sensitive.
What a JWT contains
A JWT has three dot-separated parts: header, payload, and signature. The header and payload are Base64URL-encoded JSON, readable by anyone - encoding is not encryption.
The signature is the only part that requires the signing key to produce, but you do not need it to debug claims. Decoding just means reading the first two segments.
Common claims to check: exp (expiry, Unix seconds), iat (issued at), nbf (not before), iss (issuer), aud (audience), sub (subject), and any custom claims your service adds.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cDebug a token from a log line
- Copy the full JWT from the log - include both dots, or the decode will fail.
- Open the JWT Decoder in your browser.
- Paste the token. The decoder shows the header and payload claims without sending anything to a server.
- Check exp against the current Unix time, then check iat and nbf: a token rejected as expired five minutes after issue is usually a clock-skew or timezone problem.
- Compare iss and aud with what your API expects - mismatches cause exactly the kind of 401s that leave tokens in logs.
- Redact the token before sharing logs with anyone else, even internally.
Decoding is not verifying
Decoding lets you read claims; verification proves the token was signed by the expected key and has not been modified.
For debugging, decoding is usually enough to identify the failure. For anything that grants access, always verify the signature with the issuer's public key and validate exp, nbf, iss, and aud.
If a decoder site claims to verify signatures, be suspicious: verification requires the secret key, which a remote service should never ask you to paste.
Warning: Never paste a token into a site that asks for the signing secret, and never paste tokens from production systems into unverified online tools. Local, client-side decoding is the safe default.
What the claims usually reveal
| Symptom | Claim to check | Typical fix |
|---|---|---|
| 401 immediately after issue | iat / nbf / server clock | Fix clock skew, allow leeway, sync server time |
| Token worked, then stopped | exp | Renew or re-authenticate; check expiry setting |
| Rejected by API but decodes fine | iss / aud | Align issuer and audience configuration |
| Signature invalid errors | header alg + key mismatch | Check the signing key and algorithm on both sides |
Stop tokens from reaching logs in the first place
- Never log Authorization headers or cookie values in production
- Mask or truncate tokens in debug output
- Use structured logging so sensitive fields can be filtered centrally
- Add a CI check that fails when a JWT-like pattern appears in test output
- Rotate tokens that were logged or shared in plaintext
FAQ
Q.Is it safe to decode a JWT online?
A.Only if the tool is client-side and makes no network request with your token. On this site, decoding happens locally in your browser. Any tool that uploads the token should be avoided for production credentials.
Q.Why does my token say expired when I just created it?
A.Check the server clock and timezone. exp is Unix seconds - if the server clock is ahead, or you generated the token with a different time source, a token can appear expired immediately. Clock-skew leeway usually fixes it.
Q.Do I need the secret to decode a JWT?
A.No. The header and payload are plain Base64URL-encoded JSON. You only need the secret to verify the signature, and you should never share it with a remote tool.
Q.Why does the header say alg: none?
A.A none algorithm means the token is unsigned - an attacker can forge any claims. Servers must reject none entirely. If you see it in your logs, check your token library configuration immediately.
Q.Can someone use a token they found in a log?
A.Until it expires, yes, if it is accepted as a bearer credential and the audience matches. Treat logged tokens as compromised, redact logs, and rotate the token.
References
- RFC 7519 – JSON Web Token (JWT): https://www.rfc-editor.org/rfc/rfc7519
- RFC 7515 – JSON Web Signature (JWS): https://www.rfc-editor.org/rfc/rfc7515
- RFC 4648 – Base64 and Base64URL Encoding: https://www.rfc-editor.org/rfc/rfc4648
- OWASP JWT Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html
Decode JWTs locally
Header and payload claims in your browser. Nothing is uploaded, ever.
Read the token, keep the token private
The claims in a logged JWT usually explain the failure faster than reading code. Decode locally, check the four standard claims, and fix the root cause instead of the symptom.
Use the JWT Decoder - client-side, no upload, safe for production tokens.