エラーメッセージ
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)) }