エラーメッセージ
Jwks doesn't have key to match kid or alg from Jwt
別の表記
- Jwt verification fails
- Jwks remote fetch is failed
401 のレスポンス本文です。`WWW-Authenticate` ヘッダーには `error="invalid_token"` が含まれます。`remote_jwks` を取得できないプロバイダーは「Jwks remote fetch is failed」と応答します。
Envoy / Istio — envoy.filters.http.jwt_authn (401 response body; Istio RequestAuthentication)
このエラーの意味
Envoy の `jwt_authn` フィルター(Istio の `RequestAuthentication` でも使われます)は、トークンの `kid` を持ち、その `alg` に合う種類の鍵をプロバイダーの JWKS から探しましたが、見つからなかったため、このテキストを本文として 401 を返しました。署名は一度も検証されていません。一致する鍵はあるものの署名を検証できない場合は、本文が「Jwt verification fails」になります。
発生する理由
発行者が鍵をローテーションし、Envoy のキャッシュが古い
よくある`remote_jwks` は `cache_duration`(デフォルトは 5 分)の間キャッシュされます。最後の取得より後に公開された鍵で署名されたトークンは、キャッシュが更新されるまで失敗します。
インラインまたはローカルの JWKS のコピー
よくある`local_jwks`(または Istio のインラインの `jwks:`)はスナップショットです。新しい鍵が反映されることはないため、ローテーションのたびに、設定を更新するまで認証が失敗します。
この kid を持つ鍵の種類が違う
ときどきJWKS にその `kid` はありますが、トークンが ES256 なのに RSA 鍵になっています(または JWK の `alg` が一致しません)。Envoy は両方が一致することを要求します。
トークンが別の発行者のもの
ときどき`issuer` の一致条件を絞り込んでいないプロバイダーや、別の ID プロバイダーのトークンを含むリクエストは、誤った鍵セットに対して検証されます。
修正方法
- 1.
発行者から JWKS を取得する
適切な `cache_duration` と非同期取得を設定して `remote_jwks` を使い、トークンが鍵を使う前に鍵がそろっているようにしてください。
yaml providers: issuer_example: issuer: https://issuer.example.com audiences: ["api://orders"] remote_jwks: http_uri: uri: https://issuer.example.com/.well-known/jwks.json cluster: issuer_jwks # a cluster with TLS to the issuer timeout: 5s cache_duration: 600s async_fetch: { fast_listener: false } # prefetch, and refetch in the background - 2.
Istio では jwksUri を指定する
Istiod が鍵を取得して配布します。インラインの `jwks` の値は、ローテーションのたびに手作業で更新しなければなりません。
yaml apiVersion: security.istio.io/v1 kind: RequestAuthentication metadata: name: orders-jwt spec: selector: matchLabels: { app: orders } jwtRules: - issuer: https://issuer.example.com jwksUri: https://issuer.example.com/.well-known/jwks.json # not an inline "jwks:" copy