错误信息
Expected 200 OK from the JSON Web Key Set HTTP response
jose (JavaScript) — JOSEError from createRemoteJWKSet, code ERR_JOSE_GENERIC
含义
`createRemoteJWKSet` 请求了密钥集 URL,得到的 HTTP 状态码不是 200。jose 获取 JWKS 时禁用了重定向(`redirect: "manual"`),因此 301/302 和 404、401 一样都算失败。没有加载任何密钥,也没有检查任何令牌签名;你配置的 URL 返回的不是密钥集。
原因
配置的 URL 不是 jwks_uri
常见每个提供商都使用自己的路径:Auth0 是 `/.well-known/jwks.json`,Keycloak 是 `/realms/<realm>/protocol/openid-connect/certs`,Entra ID 是 `/<tenant>/discovery/v2.0/keys`,Google 是 `https://www.googleapis.com/oauth2/v3/certs`。如果让 jose 指向颁发者 URL 或发现文档本身,得到的是 404 或非 JWKS 的响应。
端点返回了重定向
常见从 HTTP 到 HTTPS 的重定向、补全末尾斜杠的重定向,或者文件已被 CDN 移到别处,返回的都是 30x。浏览器和 curl 会悄无声息地跟随重定向;jose 不会,所以 URL 必须是最终地址。
密钥集需要身份验证,或受网络策略限制
偶见内部身份提供商有时位于要求凭证的 API 网关之后(401/403),或者出站代理会返回它自己的错误页面。JWKS 是公开数据,每个验证方都应该能在不提供凭证的情况下访问它。
获取次数过多
罕见如果验证方为每个请求都新建一个远程 JWKS 对象,每次都会重新获取密钥集,可能因此被限流(429)。只创建一次该对象并重复使用,它的缓存才能发挥作用。
修复方法
- 1.
从发现文档中读取 jwks_uri
OpenID Connect 提供商会在 `/.well-known/openid-configuration` 中以 `jwks_uri` 发布确切的密钥集 URL。在启动时解析一次,再把这个 URL 传给 `createRemoteJWKSet`。
js import { createRemoteJWKSet } from "jose"; // Resolve jwks_uri from the provider's discovery document instead of guessing it. const discovery = await fetch("https://login.example.com/.well-known/openid-configuration").then((r) => r.json()); const jwks = createRemoteJWKSet(new URL(discovery.jwks_uri)); - 2.
在不跟随重定向的情况下检查状态码
不带 `-L` 的 curl 与 jose 的行为相同。你需要的是带有 `{"keys":[...]}` 的 200;如果是 30x,它会告诉你应该改为配置哪个 URL。
bash # Status line and redirect target, without following redirects (jose does not follow them either) curl -sS -o /dev/null -w '%{http_code} %{redirect_url}\n' https://login.example.com/jwks curl -s https://login.example.com/.well-known/openid-configuration | jq -r .jwks_uri