6 min read

JWT verification — the five ways apps get it wrong

JWTs are only as secure as your verification. Missing issuer check, missing expiration check, `alg: 'none'`, and algorithm confusion all still ship in AI-generated code.

A JWT is just a signed envelope. Every property that makes it secure comes from your verification. This guide covers the five verification bugs we see most, in order of frequency.

What it is

A JSON Web Token carries a payload and a signature. Verification checks that the signature matches the payload under an expected algorithm and key, and that the declared claims (issuer, audience, expiration) match what your app expects.

Vulnerable example

// Vulnerable: decode without verify
import jwt from "jsonwebtoken";
const payload = jwt.decode(token) as { sub: string };
// Attacker forges ANY payload. jwt.decode does not verify signatures.

// Vulnerable: verify without checking alg
jwt.verify(token, publicKey);
// Vulnerable to alg: 'none' and HS256/RS256 confusion attacks.

Fixed example

// Fixed: verify with explicit algorithm and claim checks
import jwt from "jsonwebtoken";

const payload = jwt.verify(token, publicKey, {
  algorithms: ["RS256"],           // pin the algorithm
  issuer: "https://yourapp.com",   // check issuer
  audience: "api.yourapp.com",     // check audience
});
// expiration is checked by default by jwt.verify

How Securie catches it

Securie's auth specialist traces every jwt.verify and jwt.decode call, requiring explicit algorithms, issuer and audience, and flagging any `decode`-without-verify usage.

Checklist

  • Algorithms whitelist is explicit (never default or empty)
  • Issuer claim is verified
  • Audience claim is verified
  • Expiration is checked (default in most libs — do not disable)
  • JWT is rejected if the key is not a known JWK ID
  • Public keys rotated at least annually

FAQ

What about `jsonwebtoken` vs `jose`?

jose is more modern and handles JWS + JWE + JWK well. Most new apps should use it. Either is fine if verification options are explicit.