An algorithm confusion attack tricks a JWT verifier into validating a token with an unintended signing algorithm. The attacker changes the token’s alg header, potentially bypassing signature validation. section 8.3
A notable failure changes an asymmetric token from its expected algorithm to HS256. A vulnerable library may then treat the public key as an HMAC secret, accepting a forged token. section 8.3
Listing 8.7 Validating tokens with an HS256 signature
# file: ch08/jwt_validator_pyjwt_hs256.py
import jwt
def validate_token(token):
return jwt.decode( #1
jwt=token,
key="password", #2
algorithms=["HS256"], #3
audience="https://apithreats.com/api",
issuer="https://auth.apithreats.com",
)
token = <token>
print(validate_token(token))
A safe validator explicitly allows HS256, supplies its intended key, and checks audience and issuer rather than trusting the token’s algorithm choice. section 8.3
Listing 8.8 Validating tokens with a PS256 signature
# file: ch08/jwt_validator_pyjwt_ps256.py
from pathlib import Path
import jwt
from cryptography.hazmat.primitives.serialization \
import load_pem_public_key
public_key = load_pem_public_key( #1
Path("public_key.pem").read_text().encode()
)
def validate_token(token):
return jwt.decode(
jwt=token,
key=public_key, #2
algorithms=["PS256"], #3
audience="https://apithreats.com/api",
issuer="https://auth.apithreats.com",
)
token = <token>
print(validate_token(token))
For PS256, the validator loads a public key and explicitly restricts accepted algorithms, preventing an attacker from switching validation modes. section 8.3
Use these checks when implementing or reviewing JWT validation:
- Allow only the algorithm intended for that token type. section 8.3
- Test the selected JWT library with known algorithm-confusion examples. section 8.3
