devwithcoffee

JWT Decoder

Decode a JSON Web Token and read what is actually in it — claims explained, expiry checked against your clock. It runs in your tab and the token never leaves it.

Token

This runs in your tab. Nothing is uploaded, and there is deliberately no box for a signing secret — see below for why.

Decoded

Paste a token, or load the sample, to decode it.

Why this one has no “secret” box

Most JWT tools online offer a field for your signing key so they can verify the signature. That is a bad trade. A leaked token is one compromised session that expires on its own; a leaked signing key lets an attacker mint valid tokens for any user, indefinitely, and you will not see it in a log anywhere.

Verification belongs in your code or a CLI where the key already lives. Decoding — which is what you almost always actually want when debugging — needs no key at all.

A JWT is signed, not encrypted

This is the single most common misunderstanding. The three parts of a token are header.payload.signature, and the first two are plain base64url. Anyone holding the token can read every claim in it without any key whatsoever.

So: never put anything secret in a payload. Not an internal user note, not a permissions matrix you would rather not publish, not a phone number. If the contents genuinely need to be hidden, you want JWE, which is encrypted, has five parts, and cannot be decoded here or anywhere else without the key.

Reading the time claims

Things worth checking when auth is failing

Frequently asked

Is it safe to paste a JWT into an online decoder?

Only if the decoding happens in your browser. A JWT is a bearer credential: anyone holding it can act as you until it expires. A decoder that posts the token to a server has just been handed your session. This one does all the work client-side — you can confirm it by opening devtools, switching to the Network tab, and watching that pasting a token produces no requests. Even so, treat any production token you paste anywhere as worth rotating.

Why is there no box for the signing secret?

Because encouraging people to paste signing secrets into web pages is a genuinely bad habit, and a secret is far more damaging to leak than a single token — it lets an attacker mint tokens for anyone, forever. Verification belongs in your code or a CLI, not a website. Decoding needs no secret at all, and decoding is what you actually need 95% of the time.

What is the difference between decoding and verifying a JWT?

Decoding just base64url-decodes the header and payload — anyone can do it, because a JWT is signed, not encrypted. Verifying recomputes the signature with the key to prove the token has not been tampered with. Never trust a decoded claim for an authorisation decision without verifying first; the payload is attacker-controlled until the signature checks out.

Is JWT data encrypted?

No. A standard JWT (a JWS) is signed but fully readable by anyone who has it — base64url is encoding, not encryption. Never put anything secret in a payload. If you need the contents hidden, you want JWE, which has five parts instead of three and cannot be decoded without the key.

My token says alg: none. What does that mean?

It means the token is unsigned and anyone can forge one. The 'none' algorithm exists in the spec but accepting it is a classic authentication bypass — a library that honours alg:none will happily validate a token an attacker wrote by hand. Your verification code should pin an expected algorithm rather than trusting the header.


Built by Himanshu Srivastava, a backend engineer in Bengaluru. More in the tools collection.