The JWT alg none attack: how unsigned tokens get accepted

A verifier should decide which algorithms it accepts before it reads the token. alg none, in any spelling, should never be on that list for tokens from the outside world.

The JWS standard defines an algorithm called none for tokens that are already protected some other way. The token keeps its header and payload, and the signature part is simply empty, so it ends with a dot. In 2015 researchers found that several popular libraries would accept such a token when it was passed to their normal verify function, which let anyone write their own claims.

By TechCompare · Updated

Topic
alg none attack
Unsigned tokens
Category
Pitfalls
Mistakes that let forged tokens through

How this is calculated

The attack is simple. Take any valid token, change the header to {"alg": "none"}, change the payload to whatever you like, and drop the signature. A library that reads the algorithm from the header and then runs that algorithm will happily "verify" nothing and return success. Some libraries blocked the lowercase name but not None or NONE, so attackers tried every spelling. Modern libraries refuse none unless you opt in, and most make you list allowed algorithms when you verify. The risk comes back in hand-written code, in older dependencies, and in middleware that decodes a token to route a request before the real check runs. Test your own service: send it a token with alg none and an empty signature, and confirm it responds with 401. RFC 8725, the JWT best practices document, says plainly that libraries must let the caller pick the accepted algorithms and must not accept none by default. The JWT Decoder marks any alg none token as Unsigned in red and never shows it as verified, whatever key you enter.

Verdict

Pass an explicit algorithms list to every verify call, keep JWT libraries updated, and add a test that an alg none token is rejected. If a decoded token ever shows alg none in production traffic, treat it as an attack in progress and check the logs for what it tried to reach.

More JWT scenarios

Frequently asked questions

Is alg none ever legitimate?
Rarely. It's meant for tokens protected by another layer, like a TLS channel between two services that already trust each other. For tokens from browsers, apps or partners, there's no good reason to accept it.
How can I tell if my library is vulnerable?
Make a token with an alg none header, any payload, and an empty signature, then pass it to your verify code. A safe setup rejects it. Also check that verify calls pass an allowed algorithms list instead of trusting the header.
Does alg None or NONE behave differently?
The standard name is lowercase none, but some vulnerable libraries only blocked that exact spelling. Treat every capitalization as the same attack. The JWT Decoder does.