toolgix

How to Decode a JWT Safely: Decoding Isn’t Verifying

A JWT looks like random characters, but two of its three parts are just Base64url-encoded JSON that anyone can read. Decoding tells you what a token claims. It does not tell you whether the claims are true.

The three parts

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJzdWIiOiIxMjMiLCJleHAiOjE3OTQ0MDAwMDB9 . <signature>
  1. Header — the algorithm (alg) and token type, as JSON.
  2. Payload — the claims: who the token is about and when it expires.
  3. Signature — proves the first two parts were issued by someone holding the key. It is not readable JSON.

Each part is Base64url-encoded (RFC 4648 §5): like Base64 but with - and _ instead of + and /, and usually without = padding. That is why a normal Base64 decoder sometimes fails on JWTs.

Common claims (RFC 7519)

ClaimMeaning
issIssuer — who created the token
subSubject — usually the user ID
audAudience — which service should accept it
expExpiry time, in seconds since 1 January 1970 (UTC)
iatIssued-at time, same unit
nbfNot valid before this time

exp is in seconds, not milliseconds. If you compare it with JavaScript’s Date.now() (milliseconds), multiply by 1000 first. Our timestamp converter shows both.

Decoding is not verifying

Anyone can create a token with any payload. Only checking the signature with the right key — on your server, with a maintained JWT library — proves it is genuine. Also reject alg: none (an “unsecured” token defined in RFC 7518) and make sure your server only accepts the algorithm it expects.

Why “where” you decode matters

An access token is a password with an expiry date: whoever holds it can act as the user until it expires. Pasting live tokens into a website that sends them to a server leaks them. Our JWT Decoder decodes in your browser and sends nothing; you can confirm that with your browser’s network tab. For production secrets, prefer short-lived test tokens anyway.

Is the payload encrypted?
No, it is only encoded. Never put secrets in a JWT payload unless you use JWE (encrypted tokens), which have five parts.
Why does my token say “expired” when it should be valid?
Check the clocks: servers usually allow a small leeway, but a device clock that is wrong by minutes can cause it.

Sources

Related tools

More guides

All guides →

Categories

Recent and favourites

Tools you open appear here, and tools you star with “Favourite” stay at the top. This list is kept only in this browser.

Browse all 78 tools

↑ ↓ to moveEnter to openEsc to close