TSToolSphere
Back to all articles
jwt

Complete Guide to JWT Tokens: Signatures, Payload and Safety

2026-07-219 min read

Try it: free JWT Decoder

Decode JSON Web Tokens (JWT) client-side to inspect headers, payloads, and signatures.

Open →

Three parts, joined by dots

A JWT (JSON Web Token) is a compact, URL-safe token made of three Base64URL-encoded segments joined by periods: header.payload.signature.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Decoded, the header identifies the algorithm and token type: {"alg": "HS256", "typ": "JWT"}. The payload is arbitrary claims — data about the user or session: {"sub": "1234567890", "name": "John Doe", "iat": 1516239022}. The signature is a cryptographic proof that the header and payload haven't been tampered with since signing.

The payload is readable by anyone — always

This is the single most misunderstood fact about JWTs: the header and payload are Base64-encoded, not encrypted. Anyone holding the token can decode both instantly with no key or secret — paste one into any JWT decoder and read every claim in plain text. The signature proves the content wasn't altered; it does nothing to keep the content secret. Never put passwords, secrets, or sensitive personal data directly in a JWT payload — treat it like a fancy, structured cookie value that anyone can read.

What the signature actually protects against

The signature is computed over the header and payload using either:

  • HMAC (HS256/384/512): a single shared secret, known to whoever issues and whoever verifies tokens — symmetric, so both sides need the same secret.
  • RSA/ECDSA (RS256, ES256, etc.): a private key signs, a public key verifies — asymmetric, meaning the verifying party never needs the signing secret, useful when many services need to verify tokens but only one should issue them.

Either way, if anyone modifies the payload (e.g., changing "role": "user" to "role": "admin") without access to the signing secret/key, the signature verification fails and the token is rejected — assuming the verifying code actually checks it.

The classic JWT vulnerabilities

  • alg: none acceptance. Some early JWT libraries would honor a header claiming "alg": "none" and skip signature verification entirely — an attacker could simply strip the signature and modify claims freely. Modern libraries reject this by default, but it's the textbook JWT vulnerability for a reason.
  • Algorithm confusion (RS256 → HS256). If a server is configured to accept both HMAC and RSA algorithms, and an attacker knows the RSA public key (which is, by design, public), they can craft a token signed with HMAC using the public key as the HMAC secret. A server that doesn't strictly pin the expected algorithm can be tricked into treating this as a validly signed token.
  • Not validating exp (expiration). A token with no expiration check remains valid forever once issued — if leaked, it never expires on its own.
  • Storing JWTs in localStorage. Unlike httpOnly cookies, anything in localStorage is readable by any JavaScript running on the page — including injected scripts from an XSS vulnerability elsewhere on the site — making token theft easier than it needs to be.

Common mistakes

  • Treating a valid signature as proof the token hasn't expired. Signature validity and expiration are separate checks — always verify exp explicitly, don't assume a library does it by default.
  • Putting sensitive data in the payload "since it's signed." Signed ≠ encrypted — assume every claim is publicly readable.
  • Trusting client-supplied alg header values. The verifying server should specify which algorithm(s) it expects, not blindly honor whatever the token claims to use.
  • Forgetting refresh token rotation. Long-lived access tokens without a revocation mechanism mean a leaked token stays valid until it naturally expires — short-lived access tokens plus a rotating refresh token limit that exposure window.

FAQ

Can I read a JWT's payload without knowing the secret key?
Yes — the payload is only Base64URL-encoded, not encrypted; the secret is only needed to verify (or forge) the signature, not to read the claims.

Does a valid signature guarantee a JWT hasn't expired?
No — signature validity and expiration (exp claim) are checked independently; a correctly-signed but expired token should still be rejected by the verifying code.

Is it safe to store a JWT in localStorage?
It's readable by any script on the page, including one injected via XSS — an httpOnly cookie is generally safer since JavaScript can't read it directly.

What's the difference between HS256 and RS256?
HS256 uses one shared secret for both signing and verifying (symmetric); RS256 uses a private key to sign and a separate public key to verify (asymmetric) — useful when multiple services need to verify tokens without holding the signing secret.

Decode and inspect any JWT's header, payload, and signature instantly with the JWT Decoder — entirely client-side, tokens never leave your browser.

Looking for other tools?

Explore ToolSphere Homepage →