A JSON Web Token (JWT) is the long string of letters and dots that many APIs and login systems hand out after you sign in. This tool opens it up: it shows the header and the payload as readable JSON, turns the time claims into real dates in your own time zone, and tells you whether the token has expired. If the token is signed with a shared secret (HS256, HS384 or HS512), you can type the secret to check the signature too. The token is read in your browser. It is not sent anywhere, which matters because a live token is a key to somebody's account.
Decoding is not verification
This is the most important thing to know about JWTs. The header and payload are only Base64URL-encoded, not encrypted, so anyone who holds the token can read them, and anyone can write a token with any contents they like. Reading "admin": true in a decoded token proves nothing. Only a signature check shows that the token was produced by someone who knows the secret or the private key and that it was not changed afterwards. Servers must verify the signature on every request, and they must decide for themselves which algorithms they accept, never trusting the alg field of the token; a token with alg: none is unsigned and is a classic attack.
The three parts
A token is three Base64URL strings joined by dots: header.payload.signature. For the well-known example token the header is {"alg":"HS256","typ":"JWT"} and the payload is {"sub":"1234567890","name":"John Doe","iat":1516239022}. The signature is a 32-byte HMAC of the first two parts. You can check it here: with the secret your-256-bit-secret the example verifies, and with any other secret it does not. Press Example to try it.
Reading the dates
Three claims hold times, all as a number of seconds since 1 January 1970 UTC:
- exp is when the token stops being valid. A token must be refused on or after this moment.
- nbf (not before) is when it starts being valid.
- iat (issued at) is when it was created.
The tool shows each as a date in your time zone, as ISO 8601 in UTC, and as a relative time such as "3 days ago". For iat 1516239022 and exp 1516242622 the dates are 18 January 2018, 01:30:22 and 02:30:22 UTC, so the token lived for one hour. A common bug is a token whose exp was written in milliseconds: it then lies tens of thousands of years in the future. If a claim is not a valid number of seconds, the tool says so rather than showing a wrong date.
Checking a signature
For HS256, HS384 and HS512 the signature is an HMAC with SHA-256, SHA-384 or SHA-512 over header.payload, using the secret. Type the secret, or tick that it is Base64URL when your system stores it in that form. The check uses your browser's Web Crypto functions, and the secret stays on the page. Tokens signed with RS256, ES256 and similar algorithms use a private key and are checked with a public key, which this tool does not do; it says so instead of guessing.
Common problems
- "A JWT has three parts." You copied part of the token, or a line break or a quote came along. The tool removes a leading
Bearer and surrounding whitespace for you. - Invalid JSON or Base64URL. The token was cut off, or it is not a JWT.
- Five parts. That is an encrypted token (JWE); it cannot be read without the key.
- Valid signature but "Expired". The signature is fine; the token is simply too old. Clock differences between servers of a minute or two are common, so many systems allow a small leeway.
To look at the JSON more closely, use the JSON formatter; to check that a downloaded file is intact, use the file hash checker.