Error message
invalid algorithm
What it means
The token's alg header value is not in the list of algorithms your verifier accepts. jsonwebtoken checks this before touching the signature, so the token may be perfectly signed — just with a scheme you did not allow. This gate is a security feature working as designed, not a parsing bug.
Why it happens
Issuer and verifier disagree after a migration
commonThe issuer switched from RS256 to ES256 (or vice versa) but the verifier still pins the old value in its algorithms allowlist. Every fresh token then fails while old cached ones still pass, which makes the rollout look intermittent.
Allowlist inferred from the wrong key type
commonSince v9, jsonwebtoken restricts acceptable algorithms based on the key you pass: give it an RSA public key and ES256 tokens are "invalid algorithm" even if you meant to allow them. Passing an EC key while allowing only RS256 fails the same way.
A token from a different issuer
occasionalMulti-tenant systems sometimes receive tokens minted by another identity provider with a different signature scheme. The alg mismatch is then a symptom — the real problem is that the token should not be arriving at this verifier at all.
How to fix it
- 1.
Pin the allowlist to what the issuer really uses
Decode the header to see the actual alg, then set the allowlist to exactly that value — and make sure the key type matches (EC key for ES256, RSA key for RS256).
js const { header } = jwt.decode(token, { complete: true }); console.log(header.alg); // e.g. "ES256" jwt.verify(token, ecPublicKeyPem, { algorithms: ["ES256"] }); - 2.
Roll out algorithm changes in two phases
During a key/algorithm rotation, verifiers must briefly accept both schemes — each bound to its own key via kid — then shrink back to one.
js // transition window only: jwt.verify(token, keyForKid(header.kid), { algorithms: ["ES256", "RS256"] }); // after all RS256 tokens expired: jwt.verify(token, ecPublicKeyPem, { algorithms: ["ES256"] });