Utilities

JWT decoder and verifier

Decode a JSON Web Token, read its claims and dates, and check its signature. Everything runs in your browser: the token and the key are never sent anywhere.

By using these tools you accept the Terms and the Privacy page.

Decoded as you type. A leading “Bearer ” is ignored. The token stays in this page: it is never sent or added to the address bar.

HS256, HS384, HS512: the shared secret. RS, PS, ES and EdDSA: the issuer’s public key as PEM, a certificate, a JWK or a JWK set. Never a private key.

How the JWT decoder works

The JWT decoder turns a JSON Web Token into readable JSON, explains each claim and checks the signature with a secret or public key you supply. It is for developers who need to see what an identity provider put in a token, or why an API rejects it. Each problem gets a specific message, not a generic “invalid token”.

What you see after you paste a token

The token is decoded as you type, after the page strips an Authorization: or Bearer prefix, surrounding quotes and line breaks. The verdict at the top joins the signature result and the time claims, so “Signature verified, but the token expired 2 hours ago” tells you both at once.

The header and payload are shown as written in the token, only re-indented, so a repeated member or a number too big for JavaScript appears as it is. The claims table explains the registered claims of RFC 7519 and common OpenID Connect and OAuth claims such as scope and nonce, and anything else is marked as a custom claim. A token nested inside another (cty: JWT) gets a button that decodes it. The signature panel shows the algorithm, the signature’s length and its value in Base64URL and hex.

How decoding and verification work

A signed token (JWS, RFC 7515) has three Base64URL parts joined by dots. Each part is decoded strictly, and a bad character is reported with its position in the token. Tokens up to 8 MB are read in a single linear pass, even a hostile paste.

The signature is checked with your browser’s WebCrypto API over the first two parts and the dot between them. HS, RS, PS and ES tokens with SHA-256, SHA-384 or SHA-512 are supported, and EdDSA with Ed25519. ES256K and Ed448 can’t be checked, because browser WebCrypto doesn’t offer them. A kid, jku or x5u in the header is shown, never fetched: you paste the key.

Warnings worth acting on

  • A shared secret shorter than RFC 7518 requires: 32 bytes for HS256, 48 for HS384 and 64 for HS512.
  • A public key, certificate or JWKS given for an HS token: refused, because that is the RS256 → HS256 forgery.
  • A header or payload member that appears twice. Libraries disagree on which copy counts.
  • A number JavaScript can’t hold exactly, such as a 20-digit ID.
  • An RSA key under 2,048 bits.
  • No exp claim, so the token stays valid forever unless the service checks something else.
  • An iat more than a minute ahead of your device’s clock.
  • A key URL (jku, x5u) or a whole key (jwk) in the header. A service must never take its key from the token itself.
  • = padding or spare bits in a part, which strict libraries reject.

Try it, then look closer

Try a sample token makes an HS256 token valid for one hour, with its secret filled in. Change one character of the secret and the verdict turns to “The signature doesn’t match”, as it would for a wrong key or an altered token.

To inspect a single part on its own, paste it into the Base64 decoder. If a secret is too short, replace it with a long random value from the Password generator.

Updated · Maintained by Liviu Tanase

Questions

Is my token or key sent anywhere?

No. Decoding and signature checks run in your browser, with JavaScript and the browser’s WebCrypto API. The page makes no network requests with the token or the key, never puts either in the address bar or your history, and asks the browser not to translate the results or spell-check the boxes, features that can send text to a server. You can watch the Network tab of your browser’s developer tools while you use it. As a rule, don’t paste production tokens or secrets into tools that send data to a server.

Does decoding a token mean it is valid?

No. Anyone can decode a JWT: the header and payload are only Base64URL-encoded, not encrypted. A token can be trusted only when its signature checks out with the issuer’s key and its exp, nbf, iss and aud claims fit. Never put secrets in a JWT payload.

Which key do I paste?

For HS256, HS384 and HS512, the shared secret the token was signed with, as text or Base64. For RS, PS, ES and EdDSA tokens, the issuer’s public key: a PEM block (BEGIN PUBLIC KEY or BEGIN RSA PUBLIC KEY), an X.509 certificate or a JWK. You can paste a whole JWK set, such as the issuer’s jwks.json; the key is picked by the token’s kid. Never paste a private key: verifying needs only the public key.

Why doesn’t the signature match?

Usually one of these: the wrong key (keys rotate, so match the kid), a Base64 secret entered as text or the other way round, a token copied with a character missing, or a token changed after it was signed. An ES256 signature must be the raw 64 bytes JWS uses; a DER-encoded signature is reported as such. The Base64 decoder shows what a Base64 secret really holds.

How do I check if a JWT has expired?

Paste it. The verdict says “expired 3 hours ago” or “expires in 50 minutes”, read from exp against your device’s clock, and the claims table shows exp, nbf and iat in UTC and your local time. A token is expired from the exp second on. Less than a minute past exp, or before nbf, the page notes that many servers allow that much clock skew.

Can it fetch the issuer’s keys (JWKS) for me?

No, on purpose: the page fetches nothing, including a jku or x5u URL in the token, because a token must never choose its own key. Open the issuer’s JWKS yourself (its address is jwks_uri in /.well-known/openid-configuration), copy the JSON and paste it as the key. The page picks the key whose kid matches the token.

What does alg: none mean?

The token has no signature, so anyone can create or change it. Services must reject it, and this page never shows it as verified. Libraries have had bugs where an attacker set alg to none, or switched RS256 to HS256 and signed with the public key as the secret, so a service should accept only the algorithms it expects (RFC 8725). Paste a public key or certificate for an HS256 token here and the page refuses it and says why.

How are exp, nbf and iat read?

They are NumericDates: seconds since 1 January 1970 UTC. The page shows each in UTC and in your local time. A token is expired from the exp second on and isn’t valid before nbf. Servers often allow a minute or two of clock difference. A value in milliseconds or written as a string is flagged, because many libraries reject it.

Can it decrypt an encrypted token (JWE)?

No. A JWE has five parts and an encrypted payload. The page shows its header, which names the key-management and encryption algorithms. Decrypting needs the recipient’s private key, which should stay on the server.