What Is a JWT? Structure, Claims & Security Explained

September 26, 2026 · Security

JWT (JSON Web Token) is how modern apps pass identity around: after you log in, the server hands you a signed token, and you attach it to every request instead of re-sending your password. This guide explains the three-part structure, what the claims mean, and — most importantly — the security rules that separate a correct implementation from a breach waiting to happen.

What is a JWT, in one paragraph

A JWT is a compact, URL-safe string with three dot-separated parts: header.payload.signature. The header says how it's signed, the payload carries claims (who you are, when it expires), and the signature proves nobody tampered with the first two. Servers verify the signature instead of looking up a session — which is why JWTs scale so well across distributed systems.

The three parts, with a worked example

A real (unsigned-demo) token looks like this:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  • Header — {"alg":"HS256","typ":"JWT"}, base64url-encoded. Declares the signing algorithm.
  • Payload — {"sub":"1234567890","name":"John Doe","iat":1516239022}, base64url-encoded. The claims.
  • Signature — HMAC-SHA256 of header.payload using the secret. This is the tamper-evidence seal.

Anyone can read the first two parts (more on that below). Only someone with the secret can produce a valid third part.

See it yourself: paste any token into our free JWT Decoder to inspect its header, payload, claims, and expiry — entirely in your browser.

Common registered claims, explained

ClaimNameMeaning
issIssuerWho created the token ("auth.myapp.com")
subSubjectWho the token is about (usually a user ID)
audAudienceWho the token is for — reject tokens meant for someone else
expExpirationUnix timestamp after which the token is invalid
iatIssued atWhen the token was created
nbfNot beforeToken isn't valid before this time

Treat these as a verification checklist: a robust verifier checks the signature and that iss/aud match expectations and that exp/nbf bracket the current time. Checking only the signature is half the job.

Decoding vs verifying: the crucial difference

This is the misunderstanding behind a whole category of vulnerabilities. Decoding is just base64url-decoding the payload — anyone can do it, no secret needed. Verifying is recomputing the signature with the secret/key and comparing. Code that "validates" a token by decoding it and reading exp has validated nothing — an attacker can mint a token with any claims they like, because the signature check never ran.

Rule: never trust a claim you haven't verified. If your library has separate decode and verify functions, you want verify on every request path.

Signed vs encrypted: JWS and JWE

A standard JWT is a JWS (JSON Web Signature): signed for integrity, but the payload is readable. Base64url is an encoding, not encryption — pasting a token into any decoder reveals everything. If the payload must stay confidential, you need JWE (JSON Web Encryption), which actually encrypts the content. In practice, the simpler rule wins: don't put secrets in JWTs. User IDs, roles, and expiry are fine; passwords, API keys, and personal data are not.

JWT vs sessions: when each fits

  • JWTs fit distributed systems and APIs: stateless verification, no session store to scale, natural for mobile apps and microservices.
  • Sessions fit when you need instant revocation (log out everywhere, ban a user) — a server-side session dies the moment you delete it, while a JWT lives until exp unless you add revocation infrastructure (denylists, short lifetimes).

The honest trade-off: JWTs trade revocation simplicity for scalability. Short-lived access tokens plus revocable refresh tokens are the standard compromise.

Common JWT mistakes to avoid

  • Trusting the alg header blindly — the infamous "alg=none" attack: if your verifier accepts tokens that declare no signature, attackers forge at will. Whitelist expected algorithms.
  • Weak HS256 secrets — HMAC is only as strong as the secret; "secret123" falls to brute force. Use long random secrets.
  • Storing tokens in localStorage without thinking — any XSS vulnerability becomes full account takeover. Weigh httpOnly cookies (see FAQ).
  • Putting sensitive data in the payload — it's readable by design.
  • Long-lived access tokens — every leak's blast radius is the token's lifetime. Keep them short.

Frequently asked questions

What does JWT stand for?
JSON Web Token. It's a compact, URL-safe way to represent claims (pieces of information) between two parties, defined by RFC 7519. Despite the name, the "JSON" part is just the payload format — the security comes from the signature.
Is a JWT encrypted?
Not by default. A standard JWT (technically a JWS — JSON Web Signature) is signed but readable by anyone who has it: the payload is only base64url-encoded, which is encoding, not encryption. If the payload contains secrets, you need JWE (JSON Web Encryption) instead — or better, don't put secrets in tokens at all.
How long should a JWT last?
As short as practical: 5–15 minutes for access tokens is the common guidance, paired with a longer-lived refresh token (hours to days) that can be revoked. Long-lived access tokens turn every leak into a long-lived breach.
Can I decode a JWT without the secret?
Yes — decoding (reading the header and payload) needs no secret, because they're only base64url-encoded. Verifying the signature is what needs the secret (HS256) or public key (RS256). Never confuse "I decoded it" with "I trust it".
Where should I store JWTs?
It's a trade-off: localStorage is convenient but readable by any JavaScript (XSS steals it); httpOnly cookies are invisible to JavaScript but need CSRF protection. For most web apps, httpOnly + SameSite cookies with CSRF tokens is the safer default. There is no option with zero trade-offs.
What's the difference between HS256 and RS256?
HS256 uses one shared secret for both signing and verifying (HMAC) — simple, but anyone who verifies can also forge. RS256 uses an RSA key pair: the server signs with the private key, anyone verifies with the public key. RS256 fits distributed systems where verifiers shouldn't be able to mint tokens.
What happens when a JWT expires?
The `exp` claim tells verifiers to reject it after that Unix timestamp. Your application should then use a refresh token to obtain a new access token — or force re-authentication if the refresh token is expired or revoked too.

Related articles

Try the free tool