jsonwebtoken (Node.js)JWT 库
错误信息
invalid algorithm
含义
令牌 alg 头部的值不在你的验证方接受的算法列表中。jsonwebtoken 在处理签名之前就会检查这一点,因此令牌的签名可能完全没有问题——只是使用了你没有允许的方案。这道关卡是按设计正常工作的安全功能,而不是解析错误。
原因
迁移后颁发者与验证方不一致
常见颁发者已从 RS256 切换到 ES256(或者反过来),但验证方的算法允许列表中仍固定着旧值。于是每个新令牌都会验证失败,而缓存的旧令牌仍能通过,这让上线过程看起来时好时坏。
根据错误的密钥类型推断出的允许列表
常见从 v9 开始,如果你没有传入 algorithms 选项,jsonwebtoken 会根据密钥推断允许列表:给它一个 RSA 公钥,ES256 令牌就会得到“invalid algorithm”,即使你本意是允许它们。传入 EC 密钥却只允许 RS256,同样会失败。(RSA 密钥配合 algorithms: ["ES256"] 能通过这项检查,但会在下一项检查中失败,报错为“"alg" parameter for "rsa" key type must be one of: RS256, PS256, …”。)
来自其他颁发者的令牌
偶见多租户系统有时会收到由另一个身份提供商签发、使用不同签名方案的令牌。此时 alg 不匹配只是表象——真正的问题在于,这个令牌根本不应该到达这个验证方。
修复方法
- 1.
把允许列表固定为颁发者实际使用的算法
解码头部查看实际的 alg,然后让允许列表只包含这个值——并确保密钥类型匹配(ES256 用 EC 密钥,RS256 用 RSA 密钥)。
js const { header } = jwt.decode(token, { complete: true }); console.log(header.alg); // e.g. "ES256" jwt.verify(token, ecPublicKeyPem, { algorithms: ["ES256"] }); - 2.
分两个阶段上线算法变更
在密钥/算法轮换期间,验证方必须短暂地同时接受两种方案——每种方案都通过 kid 绑定到各自的密钥——然后再缩减回一种。
js // transition window only: jwt.verify(token, keyForKid(header.kid), { algorithms: ["ES256", "RS256"] }); // after all RS256 tokens expired: jwt.verify(token, ecPublicKeyPem, { algorithms: ["ES256"] });