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: exp and nbf (time), iss (issuer) and aud (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.

More guides