JWT Debugger
Decode and inspect JSON Web Tokens securely in your browser
Privacy Notice: All token decoding happens in your browser. No data is sent to any server.
How to Use
- Paste a JWT — decoding happens locally as you type
- Inspect header, payload, and signature segments
- Check the
exp/iat/nbfstatus badge - Copy the decoded JSON if you need it elsewhere
Decoding is not verification. Anyone can read a JWT — only your server can prove it's authentic.
The JWT Mistakes I See in Real Codebases
-
alg: noneaccepted by the verifier. RFC 7519 allows an "unsecured" JWT (no signature). Several libraries historically trusted it by default, which turns any user-controlled token into an admin token. Fix: set an explicit algorithm allow-list (["RS256"]), never pass the alg from the token header into your verify call. CVE-2015-9235 and the Auth0 advisory are the canonical writeups. - HS256 vs RS256 confusion. If the verifier will accept either and you publish your RSA public key (as OIDC requires), an attacker can sign an HS256 token using your public key as the HMAC secret and pass verification. Fix: pin the algorithm, don't "auto-detect" from the header.
- Clock-skew off-by-one on
exp.expis a Unix timestamp in seconds (RFC 7519 §4.1.4). Two services whose clocks disagree by even 30 seconds will reject tokens that should still be valid. Fix: allow a small leeway (most libraries call itclockTolerance) of 30–60 seconds, and run NTP on every host. - Missing
kidand no key rotation. Without akid(key ID) in the header, your verifier has to guess which key signed a token. You can't rotate without downtime. Fix: includekid, publish a JWKS endpoint, and treat signing keys like any other secret — 90-day rotation is a reasonable default. - Skipping
audandissvalidation. A token issued for service A will happily verify against service B's endpoint if both trust the same IdP and neither checks audience. This is the single most common "the signature was valid but auth was still broken" bug I've debugged.