How JWTs Work and What a JWT Decoder Can and Cannot Tell You
The three parts of a JSON Web Token, the standard claims, why decoding is not verifying, and the mistakes that make tokens unsafe.
The structure of a JWT
A JSON Web Token is three pieces of text joined by dots: header.payload.signature. The header and payload are small JSON documents encoded with URL safe Base64. The header says which signing algorithm is used, such as HS256 or RS256. The payload holds the claims, which are statements about the user and the token. The signature is computed from the first two parts and a secret or private key.
Standard claims
A few claim names are defined by the standard and are widely used.
- iss: who issued the token.
- sub: the subject, usually a user identifier.
- aud: who the token is meant for.
- exp: the expiry time, as seconds since 1 January 1970 UTC.
- nbf: the time before which the token must not be accepted.
- iat: the time the token was issued.
Decoding is not verifying
Anyone can decode a JWT, because Base64 is only an encoding. A decoder shows you the header and payload, and can convert exp and iat into readable dates. It cannot tell you whether the token is genuine.
Only a server that holds the right key can verify the signature. A token that decodes cleanly may still be forged or expired. Never make a trust decision on an application from decoded content alone.
Keep secrets out of the payload
Because the payload is readable by anyone who holds the token, it must not contain passwords, API keys or other private data. Treat it as public information that happens to be signed. If you need to hide the contents, use an encrypted token format rather than a signed one.
Mistakes to avoid
These problems appear again and again in real systems.
- Accepting the none algorithm or letting the token choose its own algorithm. The server should fix the allowed algorithms.
- Skipping the checks on exp, aud and iss after the signature passes.
- Using a weak or guessable secret with HS256.
- Keeping long lived tokens in places that scripts can read, which turns any cross site scripting bug into an account takeover.
- Putting the token in a URL, where it ends up in logs and browser history.
Using a decoder safely
A decoder is a useful debugging aid for checking claims and expiry times. Prefer one that runs in your browser, so the token is not sent to a server, and avoid pasting live production tokens into tools you do not trust.