A JWT That Trusted the Client: How One Shortcut Became Full Admin Access
Not long ago I was running a penetration test on a system that used JWTs to manage sessions. On the surface everything looked standard: a token with an exp, a signature, a basic payload. But the developer had decided to save a few lines of code and relied on the client side alone to enforce permissions.
Inside the payload was a role field that was returned to the client, and every critical check on the server trusted that value. The consequence is obvious to anyone who works in security: if I take a valid token, change the payload to role: admin, and re-encode it – and in this case without even a real signature, because the server accepted alg: none – I get full access to modules that were never meant to be open to me.
The most dangerous part is that from the user’s side everything looks legitimate. A simple request to a sensitive endpoint looked like this:
GET /api/admin/reports HTTP/1.1
Host: VULNERABLE_SITE
Authorization: Bearer eyJhbGciOiJub25lIn0.eyJ1c2VySWQiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ.
And the server would return highly sensitive business data as if I were a real administrator.
What this demonstrates, as sharply as anything can, is that no matter how sophisticated the client looks, security has to be enforced on the server. You cannot trust data that comes from the client, even when it is wrapped neatly inside a JWT.
How to do it properly
- Do not allow
alg: none, and do not allow tokens to switch algorithms freely. Pin a single signing algorithm on the server and make sure your library actually verifies it. - Do not keep critical permissions inside the JWT payload. Hold them on the server, in a database or a trusted session store. The JWT should be an identifier, not the source of truth for authorization.
- Validate every permission-sensitive request server-side. Whatever the payload claims, the server must check it for itself against the real source of truth.
- Monitor and log anomalies – such as an ordinary user trying to reach administrative paths.
A case like this can look marginal, but in practice it lets an attacker bypass every layer of defence and take control of the application. It is an excellent reminder that every small shortcut in server-side security turns very quickly into a serious business problem.
I first shared a version of this as a LinkedIn post on 2025-10-01. It is republished here, lightly edited, so it is easier to find and reference. — Erez Metula
