Mistakes to look for
- Using a decode function where a verify function is needed, so the signature is never checked.
- Accepting the algorithm named inside the token instead of pinning the expected one.
- Short, guessable or default signing secrets.
- No exp claim, or very long lifetimes for tokens that cannot be revoked.
- Secrets or personal data stored in the payload, which is only base64 encoded.
- Trusting a role or admin flag read from the token without checking it against your database for sensitive actions.
Verify with a pinned algorithm
import jwt from 'jsonwebtoken';
const payload = jwt.verify(token, process.env.JWT_SECRET!, {
algorithms: ['HS256'],
issuer: 'https://your-app.example',
});Create a strong secret
openssl rand -base64 48Storage and lifetime
- Prefer short-lived access tokens with a refresh flow.
- Where you can, store tokens in HttpOnly, Secure cookies instead of localStorage.
- Rotate the signing secret if it was ever committed or shared.
Frequently asked questions
Can users read what is inside a JWT?
Yes. The payload is base64url text. Never store anything in it that you would not show the user.
Are JWTs a bad idea?
No, but they are easy to misuse. Server-side sessions are a simpler choice when you do not need stateless tokens.