Skip to content

Security

JWT Security Flaws: How Attackers Bypass Token Authentication

By Cybersecurity Practice, VirtuesTech ·

JSON Web Tokens carry authentication and authorization for a large share of the applications we assess. They are convenient — stateless, self-contained, easy to pass between services. That same convenience is why a single implementation mistake so often becomes a full authentication bypass. This is a field note on the JWT flaws we see most in penetration tests, why they work, and what fixes actually hold.

A quick refresher

A JWT has three parts: a header naming the signing algorithm, a payload of claims (user ID, roles, expiry), and a signature over the first two. On login the server issues a token; the client returns it on each request; the server verifies the signature and trusts the claims. Every flaw below lives in that verification step — or in the assumption that it happened at all.

The "none" algorithm bypass

This is the finding that turns a moderate engagement into a critical one. Some libraries honor an alg header of none, meaning "this token is unsigned." If the server accepts it, an attacker removes the signature, edits the payload to "role": "admin" or another user's ID, and sends a token the server treats as valid.

We reported exactly this in one web-application assessment: unsigned tokens were accepted, so any user could be impersonated — including administrators — by hand-crafting a token. Chained with a world-readable storage bucket and inconsistent access controls, it was a straight path to other users' data.

Fix: pin the accepted algorithm server-side. Reject none outright, and don't let the token's own header choose how it's verified.

Missing or weak signature verification

Related but distinct: the token is "verified," but weakly. We see servers that decode the payload without checking the signature at all, HMAC secrets like secret or password123 that fall to an offline crack, and — the subtle one — services that verify an RS256 token using the public key as an HMAC secret, letting an attacker sign their own tokens with the key everyone already has.

Fix: verify every token before trusting a single claim; use a strong, rotated secret for HMAC; and keep the verification algorithm fixed rather than derived from the token.

Tokens that never die

Unlike a server-side session, a signed JWT stays valid until it expires — even after the user logs out, changes their password, or is deactivated. A token stolen from a log, a browser, or a proxy keeps working for its full lifetime.

Fix: keep lifetimes short (minutes, not days) and use refresh tokens for longer sessions. For logout, password change, and deactivation, maintain a denylist of revoked tokens so a compromised token can be killed before it expires.

Overstuffed payloads

Because the payload is only base64-encoded, not encrypted, anything you put in it is readable by anyone holding the token. We regularly find emails, internal IDs, and full role structures in tokens — sensitive on exposure, and bloating every request along the way.

Fix: carry the minimum — a user identifier and expiry. Look up roles and profile data server-side. Never place secrets or PII in a token.

The pattern behind all of these

Every JWT flaw above is a failure to treat the token as attacker-controlled input. The token arrives from the client; the client may be hostile; the server's job is to prove the token is genuine before believing a word of it. Strict signature verification, a fixed algorithm, short lifetimes with revocation, and minimal claims close the flaw classes we see most.

If you want these checked on your own application, our penetration testing and API security testing engagements test exactly this — and demonstrate any finding with a working proof of concept, not a scanner line.

Not sure where to start?

A plain-language conversation about your product, your risk, and what to do first.