Decoding a JWT is not verifying it
Updated 25 September 2026
A JWT looks opaque, but its header and payload are just Base64URL-encoded JSON. Paste one into the JWT decoder and you can read every claim. That's by design — and it's why reading a token proves nothing.
What each step tells you
- Decoding shows what the token claims. Anyone can write a token claiming
"role": "admin". - Verifying the signature shows the token was created by someone holding the key and hasn't been changed since.
- Validating claims shows the token is meant for you, right now:
expandnbf(time),iss(issuer) andaud(audience).
A server must do all three before trusting a token.
Keys and algorithms
HS256 uses one shared secret for signing and verifying, so everyone who can verify can also create tokens. RS256, PS256, ES256 and EdDSA sign with a
private key and verify with a public key, which the issuer publishes (usually as a JWKS at a URL listed in /.well-known/openid-configuration).
Verify against the key matching the token's kid.
Classic mistakes
- Accepting
alg: none— an unsigned token. Always pin the expected algorithm on the server. - Algorithm confusion — accepting HS256 when you expect RS256 and using the public key as an HMAC secret. Pinning the algorithm prevents this too.
- Skipping
aud: a valid token issued for another app is not valid for yours. - Putting secrets in the payload — it's readable by anyone who sees the token.
- Long-lived tokens with no way to revoke them. Keep access tokens short (minutes) and use refresh tokens.
Handling tokens safely
Treat tokens like passwords: don't paste production tokens into tools that send them to a server. The decoder here runs entirely in your browser, but the safest habit is to test with short-lived or test-environment tokens, and never paste private keys anywhere.