Сообщение об ошибке
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)
Что это означает
Фильтр `jwt_authn` в Envoy (его использует и `RequestAuthentication` в Istio) искал в JWKS провайдера ключ с `kid` токена и типом, подходящим к его `alg`, не нашёл такого и ответил 401 с этим текстом в теле. До проверки подписи дело не дошло. Если подходящий ключ есть, но подпись не проходит проверку, тело ответа будет другим: «Jwt verification fails».
Почему это происходит
Издатель провёл ротацию ключей, а кеш Envoy устарел
часто`remote_jwks` кешируется на время `cache_duration` (по умолчанию 5 минут). Токены, подписанные ключом, который опубликовали после последней загрузки, не проходят проверку, пока кеш не обновится.
Встроенная или локальная копия JWKS
часто`local_jwks` (или встроенный `jwks:` в Istio) — это снимок. О новых ключах он не узнаёт никогда; каждая ротация ломает аутентификацию, пока не обновят конфигурацию.
Ключ с этим kid другого типа
иногдаВ JWKS есть этот `kid`, но это ключ RSA, а токен подписан ES256 (или не совпадает `alg` в JWK). Envoy требует совпадения и того, и другого.
Токен выпустил другой издатель
иногдаПровайдер без строгого сопоставления по `issuer` или запрос с токеном от другого поставщика удостоверений проверяется по чужому набору ключей.
Как исправить
- 1.
Загружайте JWKS у издателя
Используйте `remote_jwks` с разумным `cache_duration` и асинхронной загрузкой, чтобы ключи были на месте до того, как ими начнут подписывать токены.
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