Safeguard
Application Security•

What are the top 3 security practices for handling JWTs?

Handle JWTs safely: pin algorithms and verify signatures, validate issuer, audience, type and expiry on every token, use strong keys and short lifetimes.

Safeguard Security Team
5 min read

The three practices that matter most for JSON Web Tokens are: verify the signature using an algorithm you chose, not the one the token names; validate the claims that bind a token to your service, such as issuer, audience, type and expiry; and protect the keys, with strong secrets and short token lifetimes. These come straight from IETF RFC 8725.

What is RFC 8725?

RFC 8725 is an IETF Best Current Practice, produced by consensus, that updates RFC 7519 with actionable guidance for secure JWT implementation and deployment. Its abstract notes that JWTs are widely used as a simple security token format in digital identity and other areas. Most JWT incidents trace to implementations that skipped a rule in it.

Practice one: verify with an algorithm you chose

The RFC says libraries must let the caller specify a supported set of algorithms and must not use any others. The library must make sure the alg or enc header matches the algorithm used for the operation, and each key must be used with exactly one algorithm.

Why so strict? A JWT header is attacker-controlled. If your code trusts it, an attacker can pick the check. The RFC describes one classic failure: a token re-signed with HMAC-SHA256 using the server's RSA public key as the shared secret, and a server that treats the key as a secret because the header said HS256. The RFC cites CVE-2015-9235 for that class.

The none algorithm needs its own rule. The RFC says it may be fine when the JWT is cryptographically protected by other means, and that libraries should not generate none tokens unless explicitly asked. For a token that grants access, reject it.

Constructed example: an API accepts a bearer token and calls a verify function with only the token and a key. A tester changes the header to none, removes the signature, and gets in. The fix is one argument: an explicit list of allowed algorithms.

Practice two: validate the claims, every time

A valid signature proves who signed the token. It does not prove the token is meant for you.

  • Issuer. When a token has an iss claim, the application must validate that the keys used belong to that issuer, and reject the token otherwise.
  • Audience. If one issuer serves several applications, the token must carry an aud claim, and the receiving application must check it. This stops a token for service A from being replayed against service B.
  • Type. RFC 8725 describes explicit typing with the typ header, so one kind of JWT cannot be confused with another, which it calls cross-JWT confusion.
  • Expiry and timing. Enforce exp and, where used, nbf, with a small clock skew allowance.

The RFC also says not to trust received claims or header values blindly. A kid header used for key lookup should be validated so it cannot cause SQL or LDAP injection, and following a jku or x5u URL from a token could lead to server-side request forgery.

Practice three: protect keys and limit lifetime

The RFC requires sufficient entropy for keys. In particular, human-memorizable passwords must not be used directly as the key for a keyed MAC like HS256. A weak secret allows offline brute force, since an attacker can guess against a captured token without touching your server.

Prefer asymmetric signing where verifiers are many and signers are few, so verifiers never hold signing keys. Rotate keys on a schedule and on suspicion of compromise, and plan for rotation with key identifiers.

Keep tokens short-lived. A short expiry limits what a stolen token can do. Pair it with refresh handling you can revoke. Where you must support immediate logout, keep a denylist or session state, since JWTs are valid until they expire.

Finally, do not put secrets in claims. Signed is not encrypted: anyone can read the payload of a signed token. The RFC also advises avoiding compression before encryption, because compressed data often reveals information about the plaintext.

How to check or apply this

  1. Find every place your code verifies a JWT and confirm an explicit algorithm list is passed.
  2. Reject none for any access token.
  3. Check iss, aud, exp, and where relevant typ, in one shared validation function.
  4. Sanitize kid and refuse to fetch keys from URLs in token headers.
  5. Use random keys of adequate length or asymmetric pairs, store them in a secrets manager, and rotate them.
  6. Set short lifetimes and a revocation path.
  7. Keep sensitive data out of payloads.
  8. Add tests with tampered, expired and wrong-audience tokens.

Where does Safeguard fit?

Safeguard's dependency scanning flags known vulnerabilities in the JWT libraries you use, and secrets scanning looks for signing keys committed to repositories. Correct validation logic still needs code review.

Quick check

Is a JWT encrypted?

Not by default. A signed JWT is encoded and integrity protected, but anyone holding it can read the claims. Do not store secrets in the payload.

Is checking the signature enough?

No. You must also check issuer, audience, type and expiry. Otherwise a token that was legitimately signed for another purpose could be accepted.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.