2026-08-28
A JSON Web Token (JWT) has three dot-separated parts: header, payload and signature. The header names the algorithm (typically HS256 or RS256), the payload carries claims like user id and expiry, and the signature proves the token was issued by someone holding the secret or private key.
The first two parts are only Base64URL-encoded, not encrypted — anyone with the token can decode and read them. The signature can only be verified with the secret, which is why decoding a token never proves it is valid or unexpired.
Split the string on dots. Part one might decode to {"alg":"HS256","typ":"JWT"}. Part two might contain sub (subject user id), iat (issued at), exp (expiry as a Unix timestamp) and iss (issuer). Part three is the cryptographic signature over the first two parts.
Typical payload claims include sub, iat, exp, iss, aud (audience) and custom roles or scopes. You can convert exp with the RovoTools Timestamp Converter to see exactly when a token expires in human-readable form.
A decoder only Base64URL-decodes the payload for inspection. It does not check the signature, audience, issuer or expiry. Forged tokens decode perfectly fine — the signature is what rejects them at the API, not the client.
Never treat a successfully decoded JWT as proof of identity. Only the resource server, with the correct secret or public key, can verify it.
Never paste production tokens into untrusted decoder websites. The token is a live bearer credential: anyone who copies it can call your API as that user until it expires or is revoked. Prefer local tools — the RovoTools JWT Decoder runs fully in your browser and explicitly does not verify signatures.
If a token leaks, revoke it server-side immediately: decoding cannot undo exposure. Keep access-token lifetimes short (minutes to hours), put long-lived refresh tokens in httpOnly Secure cookies with rotation, and avoid storing JWTs in localStorage where any XSS can exfiltrate them.
When a token is rejected: check exp against server time (clock skew is a common cause), confirm iss and aud match the API config, confirm the algorithm matches what the server expects (alg:none attacks are why many libraries disable none), and verify you are sending it as Authorization: Bearer … not as a query parameter.
Decode a JWT header and payload locally. Signatures are never verified or sent anywhere.
Decode Base64 back into readable text, locally.
Convert between Unix timestamps and human-readable dates.
Advertisement