JWT Security: Common Pitfalls
JSON Web Tokens (JWTs) are a compact, self-contained way to carry claims — commonly used for authentication — but they are easy to misuse in ways that fully break security. The token is only as trustworthy as the way you verify it, and several classic pitfalls turn “we use JWTs” into “we accept forged identities.” Knowing them is most of using JWTs safely.
What are the classic JWT pitfalls?#
| Pitfall | Consequence |
|---|---|
Accepting alg: none | Unsigned tokens accepted — forge any claim |
| Algorithm confusion (RS/HS) | Verify an RSA token with the public key as an HMAC secret |
| Weak HMAC secret | Brute-force the key, sign arbitrary tokens |
| No expiry / no revocation | Stolen tokens valid indefinitely |
| Trusting claims blindly | Privilege escalation via edited claims |
The alg pitfalls share a root cause: trusting the token to tell you how to verify it. The
fix is to pin the expected algorithm on the server and ignore the header’s suggestion.
How do you use JWTs safely?#
- Pin the algorithm server-side; never let the token choose.
- Use strong keys — long random HMAC secrets, or proper RSA/EC keys.
- Verify every claim you rely on — issuer, audience, expiry — server-side.
- Keep expiry short and use refresh tokens; maintain a revocation list for sensitive apps.
- Store tokens carefully — an XSS that reads a token defeats everything.
JWTs are common in OAuth 2.0 and REST APIs. More at the Web Security hub.
Frequently asked questions#
What is the alg:none vulnerability in JWT?
Some JWT libraries historically accepted a token with its algorithm header set to "none", meaning unsigned. An attacker could strip the signature, set alg to none, and forge any claims. Secure libraries reject this, and you should pin the expected algorithm server-side rather than trusting the token’s own header.
Can you revoke a JWT?
Not easily — that is the point of stateless tokens, and a common pitfall. Until a JWT expires it stays valid, so a compromised token cannot simply be cancelled. Mitigations include short expiry with refresh tokens, a server-side denylist of revoked token IDs, or token versioning tied to the user.