JWT Security Checklist: 12 Things to Verify Before You Ship

작성자

카테고리:

← 피드로
DEV Community · SHAHJAHAN MD. SWAJAN · 2026-07-28 개발(SW)

JWT authentication has more failure modes than most developers realise. Correct signature verification is necessary but far from sufficient. This checklist is what I run through before every production JWT deployment.

1. Secret Is Generated With a CSPRNG

Not a password. Not a UUID. Not a timestamp. A cryptographically secure pseudorandom number generator output.

A 256-bit CSPRNG secret takes 10^59 years to brute force at current GPU speeds.

2. Algorithm Is Explicitly Specified in verify()

// Wrong
jwt.verify(token, secret);

// Right
jwt.verify(token, secret, { algorithms: ['HS256'] });

Enter fullscreen mode Exit fullscreen mode

3. exp Claim Is Present and Validated

Short-lived tokens (15 minutes) limit the damage from leaks. Verify your library is actually checking exp — some require explicit configuration.

4. iss and aud Claims Are Validated

Validates the token was issued by your service and intended for your API. Prevents token reuse across services.

5. Tokens Are in httpOnly Cookies, Not localStorage

localStorage is readable by any script on the page. httpOnly cookies are invisible to JavaScript.

6. HTTPS Is Enforced

JWT in a query parameter over HTTP is visible in every proxy, CDN, and server log on the path. Use the Authorization: Bearer header over HTTPS only.

7. Refresh Tokens Are Server-Side Revocable

Short access tokens + server-side refresh tokens = the ability to end sessions immediately. Long-lived access tokens without refresh logic cannot be revoked.

8. The jti Claim Is Used If You Need Immediate Revocation

Store revoked jti values in Redis with TTL matching token expiry. Check on every request. Adds one Redis lookup per request — worth it for high-security endpoints.

9. Different Secrets for Each Environment

Dev secret leaks should not compromise production. Keep them separate.

10. Secret Is Not in Source Code or Version Control

Check: git log -S "JWT_SECRET" -- . — if any results appear, rotate immediately.

11. Error Messages Do Not Reveal Why Verification Failed

// Bad — tells attacker whether to try a different token or different secret
return res.status(401).json({ error: 'Token expired' });

// Good
return res.status(401).json({ error: 'Unauthorized' });

Enter fullscreen mode Exit fullscreen mode

12. Payload Does Not Contain Sensitive Data

JWT payload is base64, not encrypted. Decode any JWT in 3 seconds at jwt.io. Never put passwords, full PII, or financial data in a JWT payload.

The full version of this checklist with code examples for each point is at jwtsecretgenerator.com/blog/jwt-security-checklist-2026.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다