BackendJWTSecurityAuthenticationNode.jsBackend

JWT Security: Best Practices and Common Vulnerabilities

Understand JWT security deeply — algorithm confusion attacks, weak secrets, token storage, refresh token rotation, and implementation best practices.

Abdur Razzak

Abdur Razzak

Full-Stack Web Developer

April 21, 2025 11 min read

How JWTs Work

A JSON Web Token (JWT) consists of three base64url-encoded parts: header (algorithm and token type), payload (claims — user ID, roles, expiration), and signature. The signature is generated by the server using a secret key and verifies the token has not been tampered with. JWTs are self-contained — the server does not need to query a database to validate them, making them efficient for stateless authentication.

Common JWT Vulnerabilities

The 'none' algorithm attack: early JWT libraries accepted tokens with alg: 'none' (no signature) — always explicitly specify the algorithm and reject 'none'. The algorithm confusion attack: if your server accepts both RS256 (asymmetric) and HS256 (symmetric) algorithms, an attacker can trick the server into verifying an RS256 token using the public key as the HS256 secret — always hardcode the expected algorithm.

Token Storage: Where to Keep JWTs

Never store JWTs in localStorage — it is accessible to JavaScript and vulnerable to XSS attacks. Store access tokens in memory (JavaScript variable) for maximum security. Store refresh tokens in HTTP-only cookies (inaccessible to JavaScript) with Secure and SameSite=Strict flags. This combination protects against both XSS (cannot steal access token) and CSRF (SameSite prevents cross-origin cookie submission).

Access Tokens vs Refresh Tokens

Use short-lived access tokens (15 minutes) to limit the damage if a token is stolen. Use long-lived refresh tokens (7-30 days) stored in HTTP-only cookies to issue new access tokens without requiring re-login. Implement refresh token rotation: each time a refresh token is used, invalidate it and issue a new one. If you detect a used refresh token (replay attack), invalidate the entire session.

Token Revocation Strategies

JWTs are stateless by design — the server cannot revoke them before expiration. Workarounds: maintain a blocklist (Redis set of revoked token JTI claims — check on every request), use very short expiry times, or switch to opaque tokens (random strings stored in database) for sessions that need instant revocation. For most applications, short expiry + refresh token rotation is a good balance.

Signing Secret Best Practices

Use a cryptographically random secret of at least 256 bits (32 bytes) — never a human-readable password. Generate with: openssl rand -base64 32. Store secrets in environment variables, never in code. Rotate secrets periodically by supporting multiple valid secrets during a transition period, then removing the old one after all tokens signed with it have expired. Use asymmetric keys (RS256) when you need to verify tokens in multiple services.

Share this article

All posts
#JWT#Security#Authentication#Node.js#Backend
Abdur Razzak — Full Stack Web Developer
⭐ Top Rated

Upwork Top Rated Developer

Work With a Developer Clients Trust