JWT Security Pitfalls and How to Avoid Them

A
Author
08 Jun, 2026 2 min read 811 views

JWTs are easy to issue and easy to get wrong. Most JWT vulnerabilities come from how tokens are verified, not from the format itself.

1. Always verify, and pin the algorithm

import jwt from 'jsonwebtoken';

// Wrong: decode() does NOT check the signature
const payload = jwt.decode(token);

// Right: verify the signature and allow only the algorithm you use
const payload = jwt.verify(token, process.env.JWT_SECRET, {
  algorithms: ['HS256'],
  issuer: 'https://auth.example.com',
  audience: 'shop-api',
});

Without an explicit algorithm list, attacks like alg: none or "algorithm confusion" (an RS256 public key reused as an HS256 secret) become possible with some libraries.

2. Use strong keys

  • HS256 secrets must be long and random (32+ bytes), not "secret" or a word. Weak secrets can be brute-forced offline from a single token.
  • For multiple services, prefer asymmetric keys (RS256, ES256, EdDSA): only the auth server can sign, everyone can verify with the public key.
  • Support key rotation with a kid header and a JWKS endpoint.

3. Check the claims

  • exp - reject expired tokens (libraries do this by default; don't turn it off).
  • iss and aud - a token meant for another service must not be accepted by yours.
  • nbf and iat - sanity-check time-based claims.

4. Don't put secrets in the payload

echo 'eyJzdWIiOiI0MiIsInJvbGUiOiJhZG1pbiJ9' | base64 -d
# {"sub":"42","role":"admin"}  <- anyone can read it

5. Keep them short-lived

JWTs can't easily be revoked. Expiry is your main control: minutes for access tokens, with refresh token rotation for longer sessions.

6. Store them carefully in browsers

localStorage is readable by any script on the page, so one XSS bug leaks every token. Prefer HttpOnly, Secure cookies (with CSRF protections), or keep access tokens in memory only.

7. Re-check permissions that change

A role: admin claim stays in the token until it expires, even after you demote the user. For sensitive actions, check current permissions from the database.

Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.