Resolve "invalid signature" and algorithm confusion in JWT authentication. Prevent security vulnerabilities when switching between HMAC and RSA/ECDSA keys.
The cryptographic signature in the third segment of the JWT does not match the computed hash of the header and payload using the provided verification key. This commonly happens when symmetric HS256 secrets are mistakenly used against asymmetric RS256 public keys.
When algorithm validation is omitted, attackers can forge RS256 tokens using the public key as an HS256 secret (Algorithm Confusion Attack). Modern verification libraries throw invalid signature when keys or algorithms mismatch.
// Vulnerable: trusts alg in token header blindly
jwt.verify(token, publicKey);// Secure: explicitly restricts allowed algorithms
jwt.verify(token, publicKey, {
algorithms: ['RS256'], // Only accept anticipated asymmetric signatures
issuer: 'https://auth.wtool.dev',
});Resolution Note: Always pass the explicit `algorithms` array to reject unexpected cryptographic algorithms.
Decode header to verify `alg` is identical to what the verifier expects.
Check if an asymmetric public key was formatted with proper PEM boundaries (`-----BEGIN PUBLIC KEY-----`).
Ensure environment variable `JWT_SECRET` matches the exact signing server string without trailing spaces.
Prevent recurrence by enforcing this verification check in staging or pre-commit hooks:
import { jwtVerify, importSPKI } from 'jose';
export async function verifyJwtToken(jwt: string, pemPublicKey: string) {
const key = await importSPKI(pemPublicKey, 'RS256');
return await jwtVerify(jwt, key, {
algorithms: ['RS256'],
});
}