toolready. JWT Decoder

JWT Decoder

Decode JSON Web Tokens. See claims, algorithm, and expiry at a glance.

What this does

Splits a JSON Web Token on its dots, base64url-decodes the first two parts and pretty-prints them as JSON, alongside a summary strip: algorithm, type, issued-at and expiry. Expiry shows a real date plus the time left — in 43 min, in 6 h, in 12 d — and turns red once the token is past its exp. The signature is shown verbatim and left alone. All of it happens in the page, so pasting a production access token here does not leak it.

Does this verify the JWT signature?

No. It decodes, it does not validate. The third segment is displayed as an opaque string and never checked, because verifying it needs the issuer's HMAC secret or public key and this tool asks for neither. A token you edited by hand decodes just as happily as a real one, so treat the output as "what the token claims". Do the real verification in your backend with a JOSE library against the issuer's JWKS endpoint, checking alg, iss, aud and expiry there.

What are the three parts of a JWT?

header.payload.signature, each base64url-encoded: the URL-safe alphabet, with - and _ for + and /, and = padding usually stripped (the decoder puts it back). The standard sample token decodes to:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9      → {"alg":"HS256","typ":"JWT"}
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6…    → {"sub":"1234567890","name":"Jane","iat":1516239022}
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c  (signature, not verified)

Is the payload encrypted?

No, and this is the most common misunderstanding about JWTs. Base64url is encoding, not encryption — anyone holding the token reads every claim in it, exactly as this page just did, with no key involved. Signing protects against tampering, not against reading. Never put a password, an API key, a card number or anything you would not print in a log into a payload. If the content must genuinely be hidden you need JWE, which has five segments rather than three and is rejected here as malformed.

What do the standard claims mean?

  • iss — issuer, who minted the token.
  • sub — subject, usually the user ID the token speaks for.
  • aud — audience, the API meant to accept it. Rejecting tokens minted for someone else is your job, not a library default.
  • exp, nbf, iat — expiry, not-before and issued-at, in Unix seconds. The strip shows iat and exp; nbf is in the payload JSON.
  • jti — unique ID, for replay protection and revocation lists.

Everything else is a custom claim: scopes, roles, tenant IDs, whatever the issuer chose to include.

How do I debug a token my API is rejecting?

  1. Paste the raw token — no Bearer prefix, no quotes, no stray line breaks.
  2. Check Expires first. Most rejections are an expired token; clock skew between machines explains many of the rest.
  3. Compare iss and aud against what your API accepts — a token from the wrong tenant or environment is the next most common cause.
  4. Look at alg. A none, or HS256 where you expected RS256, means a forged or misconfigured token; a correct verifier pins the algorithm rather than trusting the header.
  5. Then check the scopes or roles claim the endpoint requires.

Why does it say the token is malformed?

Three errors are possible. "A JWT has three parts separated by dots" means the split produced the wrong number of segments — usually a truncated copy or a JWE. The header and payload errors mean a segment decoded but was not valid JSON: mangled in transit, or only partly pasted. Related: Base64, JSON formatter, and Unix timestamp converter for date claims the strip omits.