本文へスキップ
ecdsa.com
coreos/go-oidc (Go)Go

エラーメッセージ

failed to verify signature: failed to verify id token signature

別の表記

  • failed to verify signature: fetching keys oidc: get keys failed

JWKS のリクエスト自体が失敗した場合、テキストは「failed to verify signature: fetching keys oidc: get keys failed …」となり、その後に HTTP またはネットワークのエラーが続きます。

coreos/go-oidc (Go) — IDTokenVerifier.Verify with a RemoteKeySet

このエラーの意味

go-oidc はプロバイダーの鍵セットをダウンロードしましたが(`kid` が未知の場合は 1 回だけ再取得します)、公開されているどの鍵でもトークンの署名を検証できませんでした。go-oidc は「この kid を持つ鍵がない」場合と「この kid を持つ鍵はあるが署名が誤っている」場合を区別しません。どちらも、このプロバイダーが現在公開している鍵でトークンが署名されていないことを意味します。鍵セットをまったく取得できなかった場合は、代わりにメッセージの後に「fetching keys …」が続きます。

発生する理由

修正方法

  1. 1.

    ディスカバリから検証者を作成する

    `provider.Verifier` はプロバイダーのディスカバリドキュメントにある `jwks_uri` とプロバイダーの発行者を使うため、手動で設定した URL が不一致の原因になることがなくなります。

    go
    provider, err := oidc.NewProvider(ctx, "https://accounts.example.com") // discovery gives the right jwks_uri
    if err != nil {
    	return err
    }
    verifier := provider.Verifier(&oidc.Config{ClientID: clientID})
    idToken, err := verifier.Verify(ctx, rawIDToken)
  2. 2.

    トークンの kid と公開されている鍵を比較する

    `kid` が公開されていない場合、トークンは別の発行元のものか、プロバイダーが鍵のローテーションを完了していません。公開されている場合は、それに対応する鍵がこのトークンに署名していません。

    bash
    # kid in the token header vs kids the provider publishes
    python3 -c 'import base64,json,sys; h=sys.argv[1].split(".")[0]; print(json.loads(base64.urlsafe_b64decode(h+"="*(-len(h)%4))))' "$ID_TOKEN"
    curl -s "$(curl -s https://accounts.example.com/.well-known/openid-configuration | jq -r .jwks_uri)" | jq '.keys[] | {kid, alg, kty}'

関連するエラー

署名エラーデータベースをすべて見る