← All Guides
🛠️ Developer Tools

JWT Tokens: The 3 Security Mistakes You're Probably Making

7 min read · Updated June 2026

Here's a dirty secret about JWT implementations: roughly half of them have at least one of three critical vulnerabilities. And I'm not talking about obscure edge cases — I'm talking about "anyone can forge a valid token" level problems. Let me walk you through what JWT actually is, and how to not shoot yourself in the foot.

🔑 Quick refresher

A JWT is just three Base64URL strings joined by dots: xxxxx.yyyyy.zzzzz. The first part is the header (algorithm info), the second is the payload (your data), and the third is the signature (proves nobody tampered with it). That's it. It's not encrypted — anyone can decode the payload with our JWT decoder.

The Header: Where Things Go Wrong First

The header tells the server which algorithm was used to sign the token:

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

The algorithm matters because this is where mistake #1 lives.

Mistake #1: Accepting "alg: none"

This one sounds too simple to be real, but it happens. An attacker takes a valid JWT, changes the payload (like setting their user ID to an admin's), and changes the header to alg: none. Then they remove the signature entirely.

If your server doesn't explicitly reject alg: none, it sees the header, says "oh, no signature needed," and lets the attacker in with full admin privileges. This isn't theoretical — it's been found in real production systems, including some big-name SaaS products.

⚠️ The fix

Always check the algorithm server-side. If it's anything other than your expected algorithm (HS256, RS256, etc.), reject the token immediately. No exceptions.

The Payload: What You're Leaking

The payload contains claims — statements about the user and metadata. Common ones:

  • sub — the user ID
  • exp — when the token expires (Unix timestamp)
  • iat — when it was issued
  • role, permissions — application-specific data

Here's the thing: the payload is not encrypted. It's just Base64. Anyone can read it. This brings us to mistake #2.

Mistake #2: Putting Secrets in the Payload

I've seen people put API keys, internal IDs, and even passwords in JWT payloads. Don't. Decode any JWT with our JWT Decoder and you'll see exactly what I mean — everything is right there in plain text.

The Signature: Your Only Line of Defense

The signature is what makes a JWT trustworthy. For HS256 (the most common algorithm):

signature = HMACSHA256(base64url(header) + "." + base64url(payload), secret)

Without the secret, you can't forge a valid signature. With the secret, you can sign anything. Which brings us to mistake #3.

Mistake #3: Storing JWTs in localStorage

Any JavaScript on your page — including third-party scripts, browser extensions, and XSS attacks — can read localStorage. If a JWT stored there is stolen, the attacker has full access until it expires.

💡 The fix

Store JWTs in HttpOnly cookies. JavaScript can't read them, so XSS attacks can't steal them. Yes, you then need CSRF protection — but that's a solvable problem with SameSite cookies.

When to Use JWTs (and When Not To)

  • Stateless API auth — Server doesn't need a session store
  • SSO / microservices — Services can verify tokens independently
  • Mobile apps — No cookies to manage
  • Long-lived sessions — Use short-lived access tokens + refresh tokens instead
  • Storing lots of data — JWTs grow with payload size. Keep them small.

🔐 Debug your JWTs

Paste any JWT into our JWT Decoder — it instantly shows header, payload, expiration, and algorithm. 100% client-side, your tokens never leave your browser.

The Bottom Line

  1. Always reject alg: none — it's the easiest JWT exploit and still shows up in production
  2. Never put secrets in the payload — it's Base64, not encryption
  3. Use HttpOnly cookies for storage, not localStorage
  4. Keep tokens short-lived and use refresh tokens
  5. Always validate the signature and expiration server-side

Disclaimer: This guide is for informational purposes only. Always follow current OWASP guidelines for authentication implementations.