JWT security best practices

JWTs are secure when used carefully and dangerous when libraries are misconfigured. These practices follow RFC 8725 (JWT Best Current Practices) and the attacks seen in real systems.

Verification

Keys and secrets

Claims and lifetimes

Transport and storage

Classic attacks

alg: none

The attacker removes the signature and sets alg to none. Defeated by algorithm pinning.

RS256 → HS256 key confusion

The attacker signs with HMAC using your RSA public key as the secret. Defeated by binding keys to algorithms.

header:  {"alg":"HS256","typ":"JWT"}          ← was RS256
secret:  -----BEGIN PUBLIC KEY-----…         ← your public key
result:  accepted by libraries that let the token pick the algorithm

kid injection

A kid like ../../dev/null or x' UNION SELECT… abuses key lookup code. The decoder flags suspicious kid values.

Weak HMAC secrets

Tools can test billions of candidate secrets per second against a captured HS256 token. Use a generated 256-bit secret.

Cross-service replay

A token for service A is sent to service B, which skips the audience check. Always validate aud.

Paste a token to see automated observations — alg none, embedded keys, suspicious kid, lifetimes, weak secrets and more.

Run the security checks

Related: when to encrypt tokens.