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: noneor 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
- Audit JWT verification code for algorithm handling and
noneacceptance. - Configure verifiers with an explicit algorithm allowlist; reject
noneand unexpected algorithms. - Stop reading the algorithm from the token header; fix it in code.
- Ensure asymmetric and symmetric key paths cannot be confused.
- Verify signature, expiry, issuer, and audience on every request before trusting claims.
- Add tests submitting
alg: none, tampered-signature, and algorithm-confusion tokens to confirm rejection.