Paste a JWT into a decoder and you'll see readable JSON pop out instantly, no password required. For anyone who assumes a token is "encrypted," that's a little alarming — so it's worth being precise about what a JWT actually protects, and what it never claimed to.
Three parts, one string
A JWT (JSON Web Token) is three Base64URL-encoded segments joined by dots: header.payload.signature. The header describes the token (typically its signing algorithm and type). The payload is the actual data — often things like a user ID, an expiry time, and whatever "claims" the issuing system decided to include. The signature is what makes the token trustworthy.
Base64 is an encoding, not encryption. It's the same reversible text encoding used for embedding binary data in things like data URLs — anyone can decode it in one line of code, no key needed. That's true by design.
Signed, not sealed
The entire security model of a standard JWT rests on the signature, not on hiding the payload. When a server issues a token, it signs the header and payload using a secret (for HMAC algorithms like HS256) or a private key (for RSA/ECDSA algorithms like RS256). Anyone receiving the token can verify that signature using the corresponding secret or public key — confirming the token really was issued by that server and hasn't been tampered with since.
What signing does not do is hide the payload from view. If you can read this article, you can decode any JWT's header and payload with nothing but a text editor and a Base64 decoder. The signature only proves authenticity and integrity — that the claims are genuine and unmodified — not confidentiality.
This is a deliberate trade-off, not an oversight: JWTs are built to be passed around efficiently (in HTTP headers, URLs, cookies) and read cheaply by any service that needs the claims, without a round-trip to a central server. Hiding the payload would defeat that purpose.
What this means practically
- Never put secrets in a JWT payload. Passwords, raw credit card numbers, or anything else that needs to stay confidential doesn't belong in a standard signed JWT — anyone who intercepts the token can read it.
- A JWT's trustworthiness depends entirely on signature verification, which happens server-side with the secret/key — never in a browser-based decoder like this one, since decoders don't have your server's signing secret (and shouldn't).
- An expired token still decodes fine. Decoding just reads Base64; checking the
expclaim and rejecting expired tokens is a separate step your server (or library) needs to perform explicitly. - If confidentiality of the payload matters, you want a JWE (JSON Web Encryption), a related but distinct standard that actually encrypts the payload — not a plain signed JWT (JWS).
Inspecting a token
Our JWT Decoder splits a token into its header and payload and pretty-prints both as JSON, entirely client-side — useful for debugging an auth flow, checking what claims an API is actually sending, or confirming an expiry time without writing a script. It doesn't verify the signature (that needs the secret, which the tool never has), so treat the decoded output as "what the token claims," not "what's been cryptographically proven" — verification is a server-side job.