DevToolbox

JSON Web Tokens are the most common way to carry a user's identity between a client and a server, but their structure and security model are easy to get wrong. This guide breaks a JWT into its three parts, explains how signing and verification actually protect it, walks through the standard claims, and covers the mistakes that lead to real vulnerabilities. You can decode any token in the JWT Decoder.

The three parts of a token

A JWT is three Base64URL-encoded parts joined by dots: header.payload.signature. The header and payload are just encoded JSON, so anyone can read them — they are not secret. The signature is what makes the token trustworthy.

eyJhbGciOiJIUzI1NiJ9   .   eyJzdWIiOiIxMjM0NSJ9   .   Kx7...signature
     header                    payload                signature
A JWT is three dot-separated segments

The header and payload

The header names the signing algorithm, such as HS256 or RS256. The payload carries the claims: statements about the user and the token. Both are Base64URL-encoded JSON, which decodes to plain, readable objects.

// header
{ "alg": "HS256", "typ": "JWT" }

// payload
{ "sub": "12345", "name": "Ada", "exp": 1900000000 }
Decoded header and payload

How the signature protects the token

The signature is computed from the encoded header, the encoded payload, and a key. With HS256 the key is a single shared secret; with RS256 it is an RSA private key. A server verifies a token by recomputing the signature with its key and checking it matches. Because changing any character of the header or payload changes the correct signature, tampering is detected immediately.

This is why decoding is not the same as trusting: the payload is readable by anyone, but only a party with the key can produce a valid signature.

Standard claims

Several claim names are reserved by the JWT specification and carry defined meanings. Verifying exp and aud is essential to security.

ClaimMeaning
issIssuer — who created the token
subSubject — who the token is about
audAudience — who the token is for
expExpiration time (Unix seconds)
nbfNot valid before this time
iatIssued at (Unix seconds)
jtiUnique token ID

HS256 vs RS256

HS256 signs and verifies with the same shared secret, which is simple but means every party that can verify can also issue tokens. RS256 signs with a private key and verifies with the matching public key, so you can distribute the public key widely for verification while only the issuer holds the signing key. Choose RS256 when many services need to verify but not issue.

Common security mistakes

Most JWT vulnerabilities come from a few avoidable errors.

  • Trusting claims without verifying the signature.
  • Not checking exp, so expired tokens are still accepted.
  • Storing secrets in the payload, which is readable by anyone.
  • Accepting the 'none' algorithm, which skips signature verification.
  • Keeping tokens long-lived instead of using short expiries with refresh tokens.

Frequently asked questions

Is a JWT encrypted?+

A standard signed JWT is encoded and signed, not encrypted. The header and payload are readable by anyone. Only an encrypted JWT (JWE) hides its contents.

Can a JWT be tampered with?+

The readable parts can be changed, but without the signing key an attacker cannot produce a matching signature, so a verifying server rejects the modified token.

Where should a browser store a JWT?+

Prefer an HttpOnly, Secure cookie so scripts cannot read it, which limits exposure to cross-site scripting. localStorage is convenient but readable by any script on the page.

What is the difference between HS256 and RS256?+

HS256 uses one shared secret for signing and verifying. RS256 uses a private key to sign and a public key to verify, which is better when many parties need to verify tokens.

Try it now

Put this into practice with the free, in-browser tools: