Back to blog
JWTauthenticationAPIsessionstokens

JWT flaws: expiration and signature issues to test

Published on 2026-06-03 · Updated on 2026-10-294 min read
In short: A JWT is a signed token the server accepts without looking anything up. That property turns every mistake into a vulnerability: a token with no expiry stays valid forever once stolen, a server that accepts alg: none or confuses algorithms accepts forged tokens, and a weak HMAC secret can be cracked offline. Here is how these flaws are exploited, how to test for them in an hour and how to fix them.

Why JWTs are fragile by design

A JWT has three base64url-encoded parts: a header (algorithm, key ID), a payload (user ID, organization, role, expiry) and a signature. The server checks the signature and then trusts the payload. There is no server-side session to invalidate. As long as the signature is valid and the expiry has not passed, the token works. All of the security therefore rests on three things: strict signature verification, token lifetime and the secrecy of the key.

Flaw 1: tokens that never expire

We still find access tokens valid for 30 days, or with no exp claim at all. A token stolen through XSS, an application log, a support tool or a screenshot then grants lasting access. Changing the victim's password changes nothing: the token stays valid.

Fix: access tokens of 5 to 15 minutes, single-use refresh tokens with rotation, and reuse detection on old refresh tokens (a sign of theft) that revokes the whole token family.

Flaw 2: alg none and algorithm confusion

Two classic attacks target verification:

  • `alg: none`: the attacker edits the payload ("role": "admin"), sets the algorithm to none and drops the signature. A misconfigured library accepts it.
  • RS256 / HS256 confusion: the server signs with RS256 (private key to sign, public key to verify). The attacker forges an HS256 token using the public key as the HMAC secret. If the code verifies with "the key" without pinning the algorithm, the signature checks out.

Fix: pin the accepted algorithms server-side (algorithms: ['RS256']), never take the algorithm from the token header, and validate iss, aud and exp.

Flaw 3: a weak HMAC secret

An HS256 token signed with secret, changeme or the product name can be cracked offline: a single valid token is enough, and hashcat (mode 16500) tries millions of candidates per second. Once the secret is found, the attacker mints tokens for any account. An empty key causes the same problem, as shown by the JFrog Artifactory empty signing key flaw.

Fix: a random secret of at least 256 bits kept in a secrets manager, or asymmetric signing with rotation through a JWKS.

Flaw 4: the token in localStorage

Any script running on the page can read localStorage. A single XSS flaw, including one in a third-party dependency, is enough to send the token to an external server. Fix: refresh token in an HttpOnly; Secure; SameSite=Strict cookie, access token in memory, and a strict CSP.

Flaw 5: chatty or stale claims

Anyone can read a JWT payload: it is encoded, not encrypted. Putting email, salary or department in it exposes that data in logs and support tools. Conversely, some APIs read org_id or the role from the token without checking it is still current: a demoted user keeps their rights until expiry. Keep claims minimal and recheck sensitive permissions server-side.

How to test it

  1. Decode a token from your app (jwt.io or jwt_tool): note alg, exp, iat and the real lifetime.
  2. Test expiry: replay a token after its exp and after logging out. Both requests must return 401.
  3. Test `alg: none`: jwt_tool <token> -X a generates the variants. Change a role claim and send them.
  4. Test algorithm confusion: fetch the public key (often at /.well-known/jwks.json) and run jwt_tool <token> -X k -pk public.pem.
  5. Test secret strength if the algorithm is HS256: hashcat -m 16500 token.txt wordlist.txt. A secret cracked in minutes is a critical finding.
  6. Test the signature: change one character of the payload without re-signing. The server must reject it.
  7. Test refresh token reuse: an already used refresh token must be refused and the whole session revoked.
  8. Look for the token in localStorage, URLs and front-end logs.

What changes when an AI agent uses these tokens

An AI agent calling your API often gets a long-lived token, sometimes copied into its context or into the traces of its tool calls. A prompt injection can make it repeat that token in a reply, a ticket or a request to an attacker-controlled domain. Give the agent short-lived tokens, scoped to the actions it needs, and injected by the runtime instead of the prompt. Other authentication mistakes are covered in our article on JWT, OAuth and session flaws.

To check what a manipulated agent can do with your product's tokens, the Agent Red Team Express tests these scenarios in five days, with evidence.

Does your product ship an AI agent? CleanIssue tests what a stranger can make it do with the Agent Red Team Express (5 days, €1,900), or a custom red team for several agents and MCP servers. First step: a free 30-minute discovery call.

Sources

Written by
Reviewed on 2026-10-29

Related services

If this topic maps to a real risk in your stack, these are the most relevant CleanIssue audits.

Know what your agent can do before an attacker does.

A free 30-minute discovery call: you describe your agent, I tell you what I would test and what it costs. Five case studies are published.

Book a call