๐Ÿ“š Learning Hub
ยท 3 min read

How JWT Actually Works (And Why It's Not Encryption)


You use JWTs for authentication in almost every modern web app. But most developers treat them as magic tokens without understanding whatโ€™s inside. Letโ€™s fix that.

A JWT Is Three Base64 Strings

A JWT looks like this:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U

Three parts separated by dots: header.payload.signature. Each part is base64url-encoded (not encrypted โ€” anyone can decode it).

The Header

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

This tells you the signing algorithm. HS256 means HMAC-SHA256 (symmetric โ€” same secret for signing and verifying). RS256 means RSA-SHA256 (asymmetric โ€” private key signs, public key verifies).

The Payload

{
  "sub": "1234567890",
  "name": "Jane Developer",
  "iat": 1710000000,
  "exp": 1710086400
}

This is your data. Standard claims include:

  • sub โ€” subject (usually user ID)
  • iat โ€” issued at (Unix timestamp)
  • exp โ€” expiration time
  • iss โ€” issuer
  • aud โ€” audience

You can add any custom claims you want. But remember: this is not encrypted. Anyone with the token can decode the payload. Donโ€™t put passwords, credit card numbers, or secrets in here.

The Signature

This is the only part that provides security. For HS256:

HMAC-SHA256(
  base64url(header) + "." + base64url(payload),
  secret
)

The server takes the header and payload, concatenates them with a dot, and signs them with a secret key. The result is the signature.

When a token comes back, the server recomputes the signature using the same secret. If it matches, the token hasnโ€™t been tampered with. If someone changes the payload (like changing "role": "user" to "role": "admin"), the signature wonโ€™t match.

Why Itโ€™s Not Encryption

This is the most common misconception. JWTs are signed, not encrypted.

  • Signed = anyone can read the data, but only the server can create valid tokens
  • Encrypted = nobody can read the data without the key

Base64 is an encoding, not encryption. You can decode any JWT payload right now at jwt.io. If you need the payload to be secret, you need JWE (JSON Web Encryption), which almost nobody uses.

The Auth Flow

1. User logs in with username/password
2. Server verifies credentials
3. Server creates JWT with user info, signs it
4. Server sends JWT to client
5. Client stores JWT (usually localStorage or httpOnly cookie)
6. Client sends JWT with every request (Authorization: Bearer <token>)
7. Server verifies signature, reads payload, knows who the user is

The key insight: the server doesnโ€™t need to store sessions. The JWT itself contains all the user info. This is why JWTs are called โ€œstatelessโ€ โ€” the server doesnโ€™t need a database lookup to verify who you are.

Common Security Mistakes

Storing in localStorage

localStorage is accessible to any JavaScript on the page. One XSS vulnerability and an attacker has your token. Use httpOnly cookies instead โ€” JavaScript canโ€™t access them.

Not validating expiration

Always check exp. A JWT without an expiration is valid forever. If it gets stolen, the attacker has permanent access.

Using alg: none

The JWT spec allows "alg": "none" โ€” no signature at all. Some libraries accept this by default. An attacker can craft a token with "alg": "none", remove the signature, and your server accepts it. Always reject none algorithm.

Symmetric secrets that are too short

For HS256, your secret needs to be at least 256 bits (32 bytes) of random data. "mysecret" can be brute-forced. Use a proper random key.

When to Use JWTs (And When Not To)

Good for: API authentication, microservice-to-microservice auth, short-lived access tokens, single sign-on.

Bad for: Session management where you need instant revocation (you canโ€™t invalidate a JWT without a blocklist, which defeats the โ€œstatelessโ€ purpose), storing sensitive data, long-lived tokens.

The sweet spot: short-lived JWTs (15 minutes) paired with refresh tokens stored server-side. You get the stateless benefits for most requests, with the ability to revoke access through the refresh token.

Related: What is JWT? ยท How HTTPS Keeps Your Data Safe ยท What is OAuth? ยท Free JWT Decoder tool