jsonwebtoken (Node.js)JWT 库
错误信息
jwt audience invalid. expected: <audience>
占位符会被替换为你配置的值,例如“jwt audience invalid. expected: api://orders”。
含义
令牌通过了密码学验证,但其 aud 声明与验证方要求的受众不匹配。受众检查的意义在于:为一个 API 签发的令牌不能被重放到另一个 API——签名证明令牌由谁签发,aud 则证明它是签发给哪个服务的,两项检查都必须通过,才能信任其中的声明。
原因
标识符未能精确匹配
常见aud 按字符串精确比较。"https://api.example.com" 与 "https://api.example.com/"(末尾斜杠)、http 与 https,或者客户端 ID 与 API 标识符——任何一种差异都会导致失败。除非你请求特定的受众,否则 OAuth 提供商常常会把 client_id 放进 aud。
令牌是为另一个 API 签发的
常见客户端获取了服务 A 的令牌,却把它发给了服务 B。在一个身份提供商为多个 API 服务的场景中很常见:令牌请求中的 audience(受众)参数必须指明令牌将要出示给哪个 API。
aud 是数组,与代码的预期不符
偶见按规范,aud 可以是字符串数组。只要有任一元素等于任一期望值,jsonwebtoken 就认为匹配——但如果代码事先手动校验 aud 并假定它是普通字符串,遇到数组形式的声明就会出错。
修复方法
- 1.
比较令牌携带的值与你期望的值
把两边都打印出来。哪一边错了就修正哪一边:验证方的受众选项,或者客户端请求令牌时使用的 audience/resource 参数。
js const { aud } = jwt.decode(token); console.log("token aud:", aud); // e.g. "api://orders" or ["api://orders"] jwt.verify(token, key, { algorithms: ["ES256"], audience: "api://orders", // must match exactly (string, array or RegExp) }); - 2.
显式接受合法的变体
如果确实有多个标识符对这个 API 有效,就把它们都列出来——不要为了消除错误而去掉受众检查。
js jwt.verify(token, key, { algorithms: ["ES256"], audience: ["api://orders", "https://api.example.com"], });