错误信息
token is unverifiable: error while executing keyfunc: kid "2026-10" not found in key set
也可能输出为
- token is unverifiable: error while executing keyfunc
- token is unverifiable: no keyfunc was provided
“error while executing keyfunc:”之后的文本就是你的 Keyfunc 返回的内容。用 nil Keyfunc 调用 `jwt.Parse`,会得到“token is unverifiable: no keyfunc was provided”。
golang-jwt/jwt (Go) — jwt.ErrTokenUnverifiable wrapping the error your Keyfunc returned
含义
golang-jwt 无法获取用于验证令牌的密钥:你的 `Keyfunc` 返回了错误,golang-jwt 把它包装成了 `ErrTokenUnverifiable`(“error while executing keyfunc: …”)。该前缀之后的内容都是你自己的 Keyfunc 给出的消息——在复现中,是按 `kid` 查找密钥却一无所获。令牌本身既没有通过验证,也没有因自身问题被拒绝。
原因
令牌指定的密钥在服务中不存在
常见只在启动时加载一次的密钥,会在颁发者轮换密钥后过时。来自其他环境或其他颁发者的 `kid` 也会导致同样的查找失败。
无法获取密钥集
常见按需下载 JWKS 的 Keyfunc 会通过这条路径返回网络错误(DNS、TLS、超时、HTTP 404)。被包装的消息会指出真正的失败原因。
没有传入 Keyfunc
偶见`jwt.Parse(token, nil)`,或者从未初始化的 Keyfunc 变量。没有密钥来源,golang-jwt 什么都无法验证。
修复方法
- 1.
使用能自动刷新 JWKS 的 Keyfunc
基于 JWKS 的 Keyfunc 会在后台刷新密钥,并在出现未知 `kid` 时立即刷新,因此密钥轮换不会导致服务中断。
go k, err := keyfunc.NewDefaultCtx(ctx, []string{"https://issuer.example.com/.well-known/jwks.json"}) if err != nil { log.Fatalf("load JWKS: %v", err) } // Refetches the JWKS in the background and on unknown kids (rate-limited). token, err := jwt.Parse(raw, k.Keyfunc, jwt.WithValidMethods([]string{"ES256"})) - 2.
记录被包装的原因
`errors.Is(err, jwt.ErrTokenUnverifiable)` 用于识别错误类别;被包装的错误则告诉你是没查到密钥还是获取失败。
go if errors.Is(err, jwt.ErrTokenUnverifiable) { // The wrapped error is whatever your Keyfunc returned: log it, answer 401. log.Printf("cannot verify token: %v", errors.Unwrap(err)) }