A gateway log shows a token with alg set to none being accepted — find and fix the flaw
An API gateway logs every token it accepts. This entry was written for a request that returned 200, and the verification call the gateway made is shown on the same entry.
Constraints:
- the issuer signs all production tokens with
RS256and publishes its verification keys - the gateway must reject any token it cannot cryptographically verify
- the fix must not depend on reading the token before deciding how to check it
[gw] token accepted
header {"alg":"none","typ":"JWT"}
payload {"sub":"1042","role":"admin","exp":1893456000}
verify jwt.decode(rawToken) # claims taken straight from the result
outcome 200 GET /admin/users
Find and fix the vulnerability.
The gateway decodes rather than verifies, so a token declaring no algorithm carries no signature yet is trusted. Verify with a pinned algorithm and the issuer published key, reject any other alg, and read claims only after that passes.
- ✗Reading the
algheader to decide how the token should be verified - ✗Calling a decode helper and assuming it also checks the signature
- ✗Trusting a
roleclaim taken from a token that was never verified
- →Why must the accepted algorithm be pinned by the server rather than by the token?
- →What would you add to detect further unverified-token acceptance in these logs?
jwt.decode only parses and base64url-decodes the string — it performs no signature check. A token declaring no algorithm carries no signature at all, so the gateway trusted a role of admin that nothing attested. The flaw is the missing verification step, not the token itself.
The correct fix calls verification with an algorithm and key fixed on the server, so the token never chooses how it is checked. Any other alg value is rejected, and claims are read only after verification succeeds.
const claims = jwt.verify(rawToken, issuerPublicKey, {
algorithms: ['RS256'],
issuer: 'https://idp.example.com',
audience: 'api://gateway',
});
It is also worth adding a detection rule for accepted tokens with no confirmed signature — that log line should raise an alert rather than sit at info level.