All posts

April 29, 2026 · 5 min read

What a Broken JWT Actually Lets Someone Forge

JSON Web Tokens, JWTs, are a common way apps represent a logged-in session: a piece of data, signed cryptographically, that a server can trust came from itself and hasn't been tampered with. They're genuinely well-designed. They're also easy to implement in a way that quietly loses the one property that makes them trustworthy in the first place.

What a JWT actually is, in plain terms

A JWT is three parts: a header, a payload containing claims like a user ID or a role, and a signature. The signature is the whole point. It's a cryptographic proof that whoever created this token knew a specific secret key, meaning your server can trust the payload hasn't been altered since it was issued, as long as it actually checks that signature every time.

The mistake that quietly removes that guarantee

The JWT standard technically allows a token to declare "none" as its signing algorithm, meaning no signature at all. Some libraries, in certain configurations, will accept a token claiming this algorithm without actually verifying anything, because there's nothing to verify. If a server's verification code doesn't explicitly reject this, someone can hand-craft a token, set the algorithm to none, put whatever claims they want in the payload, a different user ID, an admin role, and the server accepts it as if it had been properly issued and signed.

A second, related mistake

Some implementations verify a token's signature using whatever algorithm the token itself claims to use, rather than the specific algorithm the server expects. This opens a related trick: if a server has a public key used for one signing method, an attacker can sometimes craft a token that gets verified against that same value using a different, weaker method, effectively forging a valid-looking signature without ever knowing the real private key.

What either mistake actually enables

Both boil down to the same outcome: someone who was never issued a real token can construct one that your server accepts as legitimate, containing whatever claims they choose. Set the user ID to any account, set a role field to admin, and if the verification step has either of these gaps, the server treats the forged token exactly like a real one.

How to actually check your own implementation

  • Confirm your server explicitly specifies and enforces which signing algorithm it expects, rather than trusting whatever algorithm a given token claims to use.
  • Confirm tokens using the "none" algorithm are explicitly and unconditionally rejected, not silently accepted because nothing checks for this case.
  • Use a well-established, actively maintained library for JWT handling rather than a custom implementation, since these specific pitfalls are exactly the kind of thing mature libraries have already patched against.
  • If an AI coding tool generated your auth logic, ask it directly whether the verification step pins the expected algorithm and rejects "none" explicitly, and check the actual code rather than trusting a confident-sounding answer.

None of this means JWTs are a bad choice, they're a solid, widely used standard. It means the verification step is the one part of the whole system that absolutely cannot be casual about what it accepts, because the entire security model rests on that one check actually happening correctly, every single time.

Related reading

Harbova is a security service for apps built with AI tools. Start with a free scan, and if it finds something serious, we can fix it and prove it is closed.