Skip to content
FindTool

    JWT Decoder

    Decode JWT header and payload, read claim timestamps in plain English, and optionally verify the signature.

    JWT Decoder tool

    Signature verification

    Verification runs in this tab with the Web Crypto API. The token and the key you paste are never sent anywhere.

    Signature not verified — paste a key to verify.

    What this tool does

    It splits a token into its three parts, decodes the header and payload from base64url, and renders them as formatted JSON. Timestamp claims become real dates with a relative form, so you see that a token expired forty minutes ago instead of converting 1758675600 by hand.

    Paste a key and it also verifies the signature — genuinely, with the Web Crypto API, in this tab. HS256/384/512 against a shared secret; RS, PS and ES against a public key in PEM or JWK form. Without a key it says the signature was not verified and implies nothing else.

    Common uses

    • Checking whether a 401 is caused by expiry or something else.
    • Confirming an identity provider issues the claims you expect: the right aud, scopes and subject.
    • Reading kid to see which JWKS key signed a token.
    • Proving a token was signed by the key you think, before trusting a bug report.
    • Spotting a token issued with alg set to none.

    A short example

    Three base64url segments joined by full stops:

    eyJhbGciOiJIUzI1NiJ9 . eyJzdWIiOiI0MiIsImV4cCI6MTc1ODY3NTYwMH0 . 3vQ…
         header                  payload                              signature

    which decode to:

    {"alg":"HS256"}
    {"sub":"42","exp":1758675600}

    No key was needed to read either — the point of the next section.

    Decoding is not verifying

    The header and payload are encoded, not encrypted. Anyone holding a token can read every claim, and anyone can craft one containing any claims they like. What makes a token trustworthy is the third segment: an HMAC or signature over the first two, which only the key holder could produce. A token that decodes cleanly proves nothing.

    Three failure modes matter:

    • alg: none — an unsecured token with no signature. Accepting one is CVE-2015-9235, the original JWT vulnerability. It is flagged here and never reported as verified.
    • Algorithm confusion — an attacker relabels an RS256 token as HS256 and signs it with the public key, which is not secret. A verifier that reads the algorithm from the header accepts it. Pin the expected algorithm in your own code; the override selector here lets you test that theory deliberately.
    • Embedded keys — the jwk, jku and x5u headers let a token point at its own key. Trusting them means trusting the attacker's key, so libraries ignore them by default.

    Worth knowing

    A valid signature is necessary but not sufficient. Check that iss is your issuer, aud names your service, and exp and nbf bracket the current time — with 30 to 60 seconds of leeway for clock skew.

    A recurring bug this tool flags: exp, iat and nbf are NumericDate values — seconds since the epoch (RFC 7519 §2). Passing Date.now() in produces milliseconds, and a token expiring in the year 57000.

    Frequently asked questions

    Is decoding a JWT the same as verifying it?

    No. The header and payload are only Base64url-encoded, not encrypted, so anyone holding the token can read them. Verification is a separate cryptographic check against a secret or public key, which this tool performs only when you supply that key.

    Can I trust a token just because it decodes cleanly?

    Never. An attacker can craft a token with any claims they like. Only a successful signature verification — plus checks on the issuer, audience and expiry — tells you a token is genuine.