How to Validate JWT Tokens Without Exposing Secrets

A JWT (JSON Web Token) is not encrypted — its header and payload are just Base64URL-encoded JSON, readable by anyone who has the token string. That makes JWTs easy to debug, but it also means the token itself is sensitive: anyone holding a valid, unexpired JWT can often use it to authenticate as that user. This guide covers how to inspect a JWT's structure and claims during debugging without treating the token carelessly.

Key Takeaways

  • A JWT's header and payload are readable by anyone — decoding them requires no secret and proves nothing about validity
  • Only the signature step proves a token hasn't been tampered with, and that requires the server's secret or public key
  • Never paste a live, unexpired production token into a third-party site — treat it like a password
  • Check the "exp" (expiry), "iat" (issued-at), and "alg" (algorithm) claims first — most JWT bugs are one of these three
  • A local, browser-side decoder is safe for inspecting structure; validating the signature should happen server-side or with a trusted local library, never by sending the secret to a webpage

1. Understand what decoding actually proves

A JWT has three Base64URL-encoded segments separated by dots: header.payload.signature. Decoding the header and payload just reverses Base64URL encoding — it requires no secret and works on any JWT, valid or forged. Decoding a token tells you what it claims, not whether those claims are true. Only re-computing and comparing the signature (which requires the signing secret or public key) proves the token is authentic and unmodified.

2. Decode structure locally, never on a token you don't control

For debugging your own test tokens, a browser-side JWT decoder that never transmits the token is fine — it just splits the string on "." and Base64URL-decodes the first two parts. For a real user's live production token, don't paste it into any external tool at all, even a "processes in-browser" one you haven't audited. If you need to inspect a live token, do it in a local debugger, a REPL, or your backend's logs with the token itself redacted from anything you copy elsewhere.

3. Read the claims in the right order

Once decoded, check "alg" in the header first — if it says "none", the token requires no valid signature at all, which is either a testing artifact or a serious vulnerability if accepted in production. Then check "exp" (expiration, Unix timestamp) against the current time, and "iat" (issued-at) to sanity-check the token's age. Most "why is this token rejected" bugs are an expired "exp", a clock-skew issue between servers, or a mismatched "alg" between what was signed and what the verifier expects.

4. Verify the signature server-side, not in a browser tab

Signature verification needs the secret (HS256) or public key (RS256/ES256) used to sign the token. Never paste a production signing secret into any web tool, including your own, unless it runs fully offline with no network calls — the safest place to verify a signature is your backend code or a trusted CLI library, not a browser tab that could have third-party scripts or extensions reading the page.

5. Rotate anything you suspect leaked

If you ever paste a live token or signing secret somewhere you're unsure about — a shared Slack channel, a public gist, an unaudited tool — treat it as compromised. Rotate the signing secret (which invalidates every token signed with it) or force-expire the specific user session, rather than assuming no one saw it.

Common Mistakes to Avoid

  • Treating a decoded (but not signature-verified) JWT as proof the request is authentic
  • Pasting a live production JWT into a public "JWT debugger" website
  • Pasting the signing secret into any tool to "double check" a signature, rather than verifying it in backend code
  • Not checking "exp" first when a token is unexpectedly rejected — expiry is the most common cause
  • Accepting "alg: none" tokens because a library defaulted to it during testing and the check was never re-enabled

Frequently Asked Questions

Can I tell if a JWT is valid just by decoding it?

No. Decoding only reveals the header and payload as readable JSON — it does not check the signature. A token can be decoded successfully and still be forged, expired, or signed with the wrong key. Validity requires verifying the signature against the correct secret or public key.

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

It's safe for test tokens you generated yourself with no real user data or live session tied to them. For a real, currently-valid user token, avoid pasting it anywhere outside your own backend or a fully offline local tool, since anyone who obtains a valid unexpired JWT can typically use it to authenticate as that user.

Why does my token get rejected even though the payload looks correct?

The three most common causes are: the "exp" claim has passed (token expired), the token was signed with a different algorithm or key than the verifier expects, or clock skew between the issuing and verifying servers makes a technically-valid token look expired or not-yet-valid.

Last reviewed: 2026 · Written and verified by the Dev Utilities team · Editorial policy

Report an issue with this guide →