Is Your JWT Implementation Safe, or Are You Leaking Sessions?
Key takeaways
- Never accept the algorithm named in the token header; pin the expected algorithm server-side to block algorithm-confusion and 'none' attacks.
- A JWT payload is signed but not encrypted, so anything inside it is readable by the client and by anyone who obtains the token.
- Short access-token lifetimes with refresh rotation and reuse detection are what make a stolen token expire quickly.
- Storing tokens in localStorage exposes them to any cross-site scripting flaw, so httpOnly, Secure, SameSite cookies are the safer default.
- Authentication events belong in a central log retained for 180 days, as CERT-In requires, because token forensics runs on that trail.
As of 24 October 2026: the service descriptions, prices and turnaround figures on this page are current.
What are the JWT mistakes that actually get exploited?
Four, in order of how often they are found. Algorithm confusion: the server decodes the header and honours whatever algorithm it names, so an attacker can submit a token with alg set to none, or with alg set to HS256 and the public key used as the HMAC secret. Unsigned payload trust: a token is base64url, not encrypted, so an attacker who cannot sign can still read and edit fields, and if the server does not verify the signature before reading claims, editing a role field is enough. Missing claim validation: exp, iss, aud, nbf and the subject are frequently not all checked, which permits token reuse across environments, such as a staging token accepted in production. And weak revocation: a stateless JWT cannot be revoked, so a token for a dismissed employee or a terminated vendor remains valid until it expires.
How long should a token live, and how should refresh work?
Short, and strictly rotated. A common workable pattern is a 10 to 15 minute access token and a refresh token of days, where the refresh token is stored server-side in hashed form, is bound to the device and session, and is single-use. Every refresh issues a new refresh token and invalidates the old one, and if an already-used refresh token is presented again, that is a replay signal and the whole token family is revoked. Logout then becomes meaningful rather than cosmetic, because the server can kill the session. For a banking or health product the access-token lifetime should be shorter still, and sensitive actions such as a beneficiary change should require a fresh authentication step rather than a valid token alone.
Where should tokens be stored on the client?
In an httpOnly, Secure, SameSite cookie, in almost every case. localStorage is readable by any script running on the origin, which means a single cross-site scripting flaw becomes a full session theft, and the attacker can exfiltrate the token without any user interaction. If a token must be readable by JavaScript, for a native mobile or a pure API client, treat it as a bearer secret, keep the lifetime short, rotate aggressively, and bind it where the platform allows. Also check the reverse proxy and the API gateway: many Indian deployments terminate TLS at the load balancer and then forward to the application over plain HTTP inside the network, which exposes the cookie header to anything on that segment.
How do you test a JWT implementation?
Test it adversarially and specifically: submit tokens with alg none, with the algorithm swapped, with an altered role claim, with a missing audience, with an expired exp, with a future nbf, and with a token issued by a different environment. Test whether logout actually invalidates, and whether a revoked user's token still works. AAVETech runs this as part of a fixed-price API or web application penetration test at roughly Rs 12,000 to Rs 30,000 per tester-day plus 18% GST, with a 5 to 10 working day turnaround, a retest included, and a written rules-of-engagement document so that nothing outside the agreed scope is touched.
| Check | Safe configuration | Common failure |
|---|---|---|
| Algorithm | Pinned server-side, one value | Trusting the alg header |
| Claim validation | exp, nbf, iss, aud, sub all checked | Audience not validated |
| Payload | Minimal, no secrets, no personal data | Role and PII in the token |
| Lifetime | 10-15 minute access token | Weeks-long access token |
| Refresh | Rotated, single use, reuse detected | Static refresh token |
| Storage | httpOnly, Secure, SameSite cookie | Token in localStorage |
What are the common questions about J?
Get a straight answer on this
Send us your token issuance and validation code paths and we will return a fixed-price session security review with a signed rules-of-engagement document.
Send us the details See pricing