About the JWT Decoder
A JSON Web Token is three Base64url-encoded segments joined by dots: a header saying how the token was signed, a payload carrying the claims, and a signature over the first two. The payload is not encrypted. Anyone holding the token can read every claim in it, which surprises people who assume that because a token looks like random characters, its contents are hidden. This tool does what any recipient of the token could do anyway - decodes the first two segments and shows you what is inside.
It also does the arithmetic you would otherwise do by hand. The exp, iat, and nbf claims are NumericDate values, seconds since the Unix epoch, and reading 1516239022 as a date in your head is not a skill worth developing. Each one is shown as a UTC timestamp with a plain-language note about how long ago or how far ahead it falls, and the token gets an overall status of active, expired, or not valid yet.
Your token never leaves the browser. That matters more here than for most tools, because a JWT is usually a live credential: pasting a production access token into a site that posts it to a server hands that server your session.
How to use this tool
- Paste your token into the box. It is decoded as you type - there is no submit button and no upload.
- Read the status strip first. It tells you whether the token is active, expired, or not valid yet, based on the exp and nbf claims and your computer's clock.
- Check the Header panel for the alg value. That is the algorithm the issuer signed with, and it decides what a verifier needs in order to check the signature.
- Read the Payload panel for the raw claims, or the Claims table below it for the same data with registered claims named and timestamps converted to dates.
- Use the Copy button on either panel to lift the decoded JSON out - it is already pretty-printed, so it drops straight into a bug report.
Decoding is not verification
Decoding a token tells you what it says. Verification tells you whether to believe it. They are completely different operations, and only the second one requires a secret: an HMAC algorithm such as HS256 needs the shared signing key, and an asymmetric one such as RS256 or ES256 needs the issuer's public key. This tool has neither, so it deliberately does not display a verified or not verified verdict on the signature.
That distinction is not academic. A token whose payload decodes cleanly and whose claims all look sensible can still be one an attacker wrote from scratch a second ago. The signature is the only part that establishes the token came from your issuer and has not been edited since. Never make an authorization decision in your own code on the basis of a decoded payload - decode for debugging, verify for access.
The alg: none attack, and why the header is a warning label
The JWT specification permits an unsecured token whose header declares alg as none and whose signature segment is empty. The intended use was narrow: tokens whose integrity is already guaranteed by the transport carrying them. In practice it produced one of the most reliably exploited authentication bugs of the last decade, because several early libraries would happily verify such a token and report success - an attacker could take a valid token, rewrite the payload to claim admin, set alg to none, drop the signature, and be believed.
This tool flags any alg: none token loudly for that reason. The related family of bugs is algorithm confusion, where a service that expects RS256 is handed an HS256 token signed with the RSA public key as if it were an HMAC secret. Since the public key is public, anyone can forge tokens that way. The fix in both cases is the same: the verifier must decide which algorithm it accepts, rather than reading that decision out of the attacker-supplied header.
Reading exp, iat, and nbf
All three are NumericDate: an integer count of seconds since 1970-01-01 UTC. The most common bug in code that handles them is comparing one against JavaScript's Date.now(), which returns milliseconds - a thousand-fold difference that makes every token look valid until roughly the year 55000. If your expiry checks never fire, that factor of 1000 is the first thing to check.
The claims mean different things. The exp claim is the moment the token stops being acceptable, nbf is the moment it starts, and iat records when it was issued. Verifiers are expected to allow a small clock skew, usually under a minute, on both exp and nbf, because the issuer's clock and the verifier's clock are never exactly the same. A token that this tool reports as freshly expired may still be accepted by a service configured with a skew allowance.
A token with no exp claim never expires by itself, which is worth noticing when you see it. Such tokens have to be revoked some other way - a deny list, a token version counter, or a rotated signing key - and if none of those exists, the token stays valid until the key changes.
Frequently asked questions
- Is my token sent anywhere?
- No. Decoding happens entirely in your browser and nothing is uploaded or logged. Close the tab and the token is gone. This is why the tool is safe to use with a real token, though rotating any credential you have pasted into a website - any website - remains good hygiene.
- Why does it not tell me whether the signature is valid?
- Because it cannot without the key. Checking an HS256 signature needs the shared secret, and checking an RS256 one needs the issuer's public key. Asking you to paste your signing secret into a web page to get a green tick would be a worse trade than the tick is worth, so the tool decodes and says so plainly.
- Can I edit the payload and get a working token back?
- No, and no tool can without the signing key. Changing a single character of the payload invalidates the signature, and producing a new valid signature requires the secret or private key the issuer used. That is the entire point of the signature.
- My token has only two segments. Is it broken?
- It is not a signed JWT in the usual sense. A JWS has three segments; five segments means a JWE, which is encrypted rather than merely encoded, and cannot be read without the decryption key. Two segments usually means the token was truncated in transit - a common result of copying from a log line that wrapped, or of a URL length limit.
- Why do exp and iat look like huge numbers?
- They are seconds since 1 January 1970 UTC, the format the JWT spec calls NumericDate. The Claims table converts each one to a readable UTC timestamp and adds how far in the past or future it falls, so you do not have to.
