Security · 5 min read
Creating and Signing JWTs Safely
Reading a JWT is easy; issuing one correctly takes a few deliberate decisions. This guide walks through what to put in the token, how to sign it, and the mistakes that have caused real breaches.
Try it yourself with the related tool.
Build and sign a JWT →Advertisement
Keep the payload small and public-safe
Include only what the receiver needs to make a decision: a subject ID in sub, an expiry in exp, the issuer in iss, the intended audience in aud, and perhaps a role. Remember that the payload is only Base64URL-encoded — anyone can read it — so emails, internal notes, and secrets do not belong there.
HS256 or RS256?
HS256 signs with a shared secret: whoever can verify can also issue tokens. That is fine when one service does both. RS256 and ES256 sign with a private key and verify with a public key, so many services can check tokens without being able to mint them. Pick asymmetric keys as soon as more than one service verifies tokens.
For HS256, use a random secret of at least 32 bytes — never a word or a short phrase, because offline brute force against a captured token is easy.
Expiry and revocation
A JWT is valid until it expires, and there is no built-in way to revoke one early. Keep access tokens short — five to fifteen minutes is common — and pair them with a refresh token stored server-side that can be revoked. Use iat and nbf if you need to reject tokens issued before an event such as a password change.
Mistakes to avoid
On the verifying side, pin the expected algorithm rather than trusting the token's header — the infamous alg: none and HS/RS confusion attacks both rely on servers that do. Always check exp and aud. And never log full tokens: a token in a log file is a working credential until it expires.
