Skip to main content

JWT Decoder & Verifier

JWT Decoder

Table of Contents

Quick Answer

A JSON Web Token (JWT) is three base64url-encoded parts separated by dots: a header that names the signing algorithm, a payload of claims about the subject, and a signature over the first two. Anyone can read the header and payload; only a holder of the right key can produce a valid signature. This tool decodes a token, explains its claims, flags the mistakes that get JWTs exploited, and verifies the signature, all without the token leaving your browser.

Paste a token to see its header, payload, each registered claim in plain words, whether it has expired, and a list of warnings. If you have the shared secret or the issuer's public key, you can verify the signature as well. Nothing you type is transmitted or stored; the decoding and the cryptography run in your browser's own Web Crypto API.

JWT Decoder & Verifier

Privacy note: this tool runs in your browser. The token, secret and key you enter are not submitted to Insecure Lab or any third party. Treat live tokens as credentials: use an expired or test token where you can, and never paste a private key.

Paste a token to decode it.

Header
Payload
Claims
ClaimValueMeaning / time
Warnings
  • Paste a token to see what it says about itself.
Verify the signature

How to read the result

  • Header and payload are shown exactly as encoded, pretty-printed. If either is not valid JSON the status line says so; the token was truncated or is not a JWS.
  • Claims lists every payload field. Registered claims get a plain-English meaning; exp, nbf and iat are also shown as dates.
  • The time line tells you whether the token is expired, not yet valid, valid for how long, or has no expiry at all.
  • Warnings are the checks a careful verifier makes and a careless one skips. A clean list is not a pass: the signature still has to verify.
  • Verify shows the fields that match the algorithm in the header: a secret for HMAC, a public key for RSA or ECDSA. A valid result means the token was not altered after signing by whoever holds that key; it says nothing about whether the key is the right one for your system.

What is a JWT?

A JSON Web Token is a compact, URL-safe way to pass a set of claims between two parties, defined in RFC 7519. The claims are a JSON object; the token wraps that object in a signature (JWS, RFC 7515) or, less often, encrypts it (JWE). Almost every JWT you meet in practice is a signed JWS: an authorization server issues it after login, and APIs accept it as proof of who is calling without looking anything up.

That statelessness is the whole appeal and the whole risk. The API trusts the token because the signature checks out, so every weakness in how the signature is produced, chosen or checked becomes a way to be someone else. Most real JWT breaches are not broken cryptography; they are a verifier that believed what the token said about itself.

Structure of a token

A signed token is three base64url strings joined by dots:

header.payload.signature

PartContentsWho can read itWho can produce it
HeaderJSON: alg (signing algorithm), typ, optionally kid (key id), jku, x5uAnyoneAnyone
PayloadJSON claims: registered ones such as iss, sub, exp, plus whatever the issuer addsAnyoneAnyone
SignatureMAC or digital signature over base64url(header) + "." + base64url(payload)Anyone (it is just bytes)Only a holder of the key

Two consequences follow. First, base64url is an encoding, so the header and payload are public to anyone who holds the token; a JWT must never carry secrets. Second, the signature covers the header too, which is why the alg field matters: it tells the verifier how to check the signature, and a verifier that obeys it without question can be told to check nothing.

Registered claims

RFC 7519 reserves seven short claim names. None is mandatory, but a verifier should insist on the ones that matter to it.

ClaimNameWhat a verifier should do with it
issIssuerCompare with the issuer you trust; reject anything else, even if the signature is valid.
subSubjectThe identity the token speaks for. Use it as the user id; do not take a user id from an unsigned source as well.
audAudienceReject tokens whose audience does not include your service. Without this check a token for service A works on service B.
expExpiration timeReject after this time, allowing at most a minute or two of clock skew. Treat a missing exp as a defect.
nbfNot beforeReject before this time.
iatIssued atUseful for maximum-age policies and for noticing tokens from the future.
jtiJWT IDStore it when you need revocation or single use; it is the only handle you will have.

Times are seconds since the Unix epoch, which is why the tool translates them. Everything else in the payload is a private or public claim defined by the application; name, email, roles and scope are common.

Common JWT vulnerabilities

These are the failure modes the warnings panel looks for. Each has been exploited in widely used software; the first two together are the reason the 2015 library advisories and RFC 8725 exist.

WeaknessHow it is abusedDefence
alg: none acceptedStrip the signature, set alg to none, edit the claims. A verifier that honours the header accepts it.Pin the accepted algorithms in the verifier configuration; never derive them from the token.
Algorithm confusionA token meant for RS256 is re-signed with HS256 using the server's public key as the HMAC secret. A library that picks the algorithm from the header and is handed the public key as "the key" verifies it.Same fix: one expected algorithm per key, enforced by the verifier. Use typed key objects where the library offers them.
Weak HMAC secretShort or dictionary secrets are brute-forced offline from a single captured token; tooling makes this a minutes-long job.At least 256 bits of random secret for HS256, from a key store, rotated. Or move to an asymmetric algorithm.
Untrusted kid, jku, x5uThe header tells the verifier which key to use. If kid is used as a file path or SQL fragment, or jku is fetched from any URL, the attacker supplies the key.Treat header fields as untrusted lookup values against an allow-list; fetch keys only from pre-configured locations.
No expiry or very long lifeA leaked token (logs, browser extension, referrer header) stays valid for weeks or forever.Short exp, refresh tokens for continuity, jti-based revocation for anything long-lived.
Missing aud / iss checksA valid token from one service or tenant is replayed against another that shares the signing key.Verify both claims against expected values, not just the signature.
Secrets in the payloadPasswords, personal identifiers or internal data placed in claims are readable by anyone holding the token, and end up in logs.Claims are public. Keep them to identity and authorization data; encrypt (JWE) if you must carry more.
Tokens in localStorageAny cross-site scripting flaw on the page reads the token and the attacker becomes the user, often from another country, for the token's whole life.Prefer an HttpOnly, Secure, SameSite cookie for browser sessions; keep access tokens short-lived.

The pattern across the table: the token is attacker-controlled input, and every field in it, including the ones that describe how to verify it, must be checked against what the verifier already expects. The OWASP API Security Top 10 files most of these under broken authentication.

Best practices for issuing and verifying JWTs

  • Configure the algorithm, do not read it. The verifier accepts exactly the algorithms (and keys) it was built with; the alg header is checked against that list, never used to choose.
  • Prefer asymmetric signing (ES256 or PS256; RS256 is acceptable) whenever more than one party verifies tokens. Publish keys through a JWKS endpoint you control, with kid values the verifier already knows.
  • Validate every relevant claim: exp and nbf with small skew, iss equals the expected issuer, aud contains this service, and a maximum age via iat if tokens are long-lived.
  • Keep tokens short-lived and use refresh tokens, which can be revoked, for session continuity.
  • Do not put secrets in claims. If the data is confidential, use JWE or keep it server-side keyed on sub.
  • Use a maintained library with explicit algorithm allow-lists and typed keys, and keep it updated; most historic JWT exploits were library defects.
  • Protect the token in transit and at rest: TLS only, no tokens in URLs or logs, HttpOnly cookies for browsers where possible.
  • Plan revocation before you need it: short expiry limits the damage, and a jti deny-list handles the rest.

The OWASP JSON Web Token Cheat Sheet expands each of these with code, and RFC 8725 is the normative list. Reviewing an existing implementation against them is part of the API security guide.

Verifying a signature with this tool

For HS256, HS384 and HS512 the tool needs the shared secret; tick the box if the secret is stored base64-encoded, as some identity providers do. For RS, PS and ES algorithms paste the issuer's public key as a PEM block beginning -----BEGIN PUBLIC KEY----- or as a single JWK object (the entries inside a JWKS document's keys array). The check is performed with your browser's Web Crypto API. EdDSA tokens are decoded but not verified, because browser support for Ed25519 is still uneven.

Limitations

  1. It verifies the signature you ask it to. A valid result with a key you pasted says the token matches that key; whether that key is the one your production verifier trusts is for you to know.
  2. It cannot see server-side state. Revocation lists, session stores and key rotation status live on the issuer.
  3. It does not decrypt JWE. Five-part encrypted tokens need the recipient's private key and are out of scope for a page you should never paste private keys into.
  4. Warnings are heuristics. They catch the common mistakes, not every policy a given system might require.

JWT Decoder FAQs

The decoder runs entirely in your browser; the token is not sent to Insecure Lab or anyone else, and nothing is stored. Even so, a token from a live system is a credential: prefer an expired one, a test one, or the built-in sample. Never paste a private key anywhere.

Because a JWT is encoded, not encrypted. Base64url is a transport format, not protection. The signature proves the token was not altered; it does not hide the contents. Anything confidential must not be in the payload, or the token must be encrypted (JWE).

That the header and payload are exactly what the holder of the key signed. It does not prove the token is current, meant for your service, or issued by the party you expect: a verifier must also check exp, nbf, aud and iss, and must only accept the algorithms it was configured for.

The JWS specification allows an unsigned token with alg set to none. Libraries that honoured the header blindly accepted any token that claimed to be unsigned, so an attacker could remove the signature and edit the claims. Modern libraries refuse none unless explicitly enabled; your verifier should pin the algorithms it accepts.

HS256 uses one shared secret for signing and verifying, so every verifier can also forge tokens. RS256, PS256 and ES256 sign with a private key and verify with a public one, so verifiers cannot mint tokens. Use an asymmetric algorithm whenever more than one service verifies, and use ES256 or PS256 for new systems.

Access tokens should live minutes to a few hours and be paired with a refresh mechanism; the shorter the life, the less a leaked token is worth. Long-lived tokens need a revocation list keyed on jti, which removes most of the statelessness that made JWTs attractive.

Summary

A JWT is readable by anyone and trustworthy only after its signature and claims have been checked against what the verifier already expects. Use this decoder to see what a token carries, to catch missing expiry, unsafe algorithms and leaky claims early, and to confirm a signature against a key you hold. Then make sure the real verifier is at least as strict as the warnings panel.

Sources and further reading