Skip to main content

JWT none Algorithm Acceptance

Accepting JWTs with alg:none or choosing the verification algorithm from the token header lets attackers forge valid-looking tokens and bypass authentication. Pin an algorithm allowlist server-side, always require a verified signature, and validate standard claims.

The JWT none algorithm anti-pattern is a class of authentication bypass where a server verifies JSON Web Tokens in a way that trusts the token itself to declare how it should be validated. JWTs carry an alg header naming their signing algorithm. If the server honors alg: none (meaning "unsigned"), or selects the verification algorithm from the attacker-controlled header, an attacker can forge tokens that the server accepts as authentic.

Why It Happens

The JWT specification includes none as a legitimate value for unsigned tokens, and some libraries historically accepted it by default. Verification code that reads alg from the header to decide how to check the signature seems natural — the token says how it was signed — but it hands algorithm choice to the attacker. Algorithm confusion (RS256 vs HS256) arises when code passes a public key into a verifier that the attacker tricks into treating it as an HMAC secret.

Why It Hurts

These flaws break authentication entirely. With alg: none accepted, an attacker crafts a token with any claims they like — admin role, another user's ID — and no signature, and the server trusts it. With algorithm confusion, an attacker signs a forged HS256 token using the server's public RSA key (which is, by definition, public) as the HMAC key, and a careless verifier validates it. Either way the attacker impersonates any user, including administrators, with no credentials.

Warning Signs

  • The verifier accepts alg: none or has no explicit allowed-algorithm list.
  • Verification reads the algorithm from the token header rather than fixing it server-side.
  • The same key path handles both RS256 and HS256 without distinction.
  • A token with a stripped or altered signature is still accepted.

Better Alternatives

Pin the accepted algorithm server-side: configure the verifier with an explicit allowlist (e.g. only RS256) and reject anything else, including none. Never derive the verification algorithm from the token's own header. Use a well-maintained JWT library and its strict verification API, supplying the expected algorithm and key explicitly. Always require and verify a valid signature before reading claims. Keep token lifetimes short and validate exp, iss, and aud. Where simpler, consider opaque server-side session tokens that carry no self-described algorithm at all.

How to Refactor Out of It

  1. Audit JWT verification code for algorithm handling and none acceptance.
  2. Configure verifiers with an explicit algorithm allowlist; reject none and unexpected algorithms.
  3. Stop reading the algorithm from the token header; fix it in code.
  4. Ensure asymmetric and symmetric key paths cannot be confused.
  5. Verify signature, expiry, issuer, and audience on every request before trusting claims.
  6. Add tests submitting alg: none, tampered-signature, and algorithm-confusion tokens to confirm rejection.