Перейти к содержимому
ecdsa.com
PyJWT (Python)JWKS и обнаружение ключей

Сообщение об ошибке

Unable to find a signing key that matches: "2026-10"

Также выводится как

  • jwt.exceptions.PyJWKClientError: Unable to find a signing key that matches: "2026-10"
  • Unable to find a signing key that matches: "None"

Значение в кавычках — это `kid` токена; `"None"` означает, что в заголовке нет `kid`.

PyJWT (Python) — jwt.exceptions.PyJWKClientError from PyJWKClient.get_signing_key_from_jwt

Что это означает

`PyJWKClient` загрузил набор ключей и не нашёл ключа подписи, у которого `kid` совпадает с `kid` из заголовка токена (он показан в кавычках). Встретив неизвестный `kid`, PyJWKClient один раз обновляет набор ключей, так что этого ключа сейчас действительно нет по этому URL. `"None"` в кавычках означает, что в токене вообще нет `kid`.

Почему это происходит

Как исправить

  1. 1.

    Сравните kid токена с загруженными ключами

    `get_signing_keys(refresh=True)` показывает, какие именно ключи может использовать PyJWKClient. Если `kid` токена там нет, проблема в издателе или в URL, а не в вашем коде.

    python
    print(jwt.get_unverified_header(token).get("kid"))
    for key in client.get_signing_keys(refresh=True):
        print(key.key_id, key.algorithm_name)
  2. 2.

    Используйте один общий PyJWKClient

    Если создавать клиент на каждый запрос, кеширование не работает и каждый вызов обращается к издателю. Долгоживущий клиент с кешем ключей всё равно загрузит набор заново, когда появится новый `kid`.

    python
    from jwt import PyJWKClient
    
    # Module level: one client, cached keys, refetch on an unknown kid.
    JWKS = PyJWKClient("https://issuer.example.com/.well-known/jwks.json", cache_keys=True, lifespan=600)
    
    def verify(token: str) -> dict:
        signing_key = JWKS.get_signing_key_from_jwt(token)
        return jwt.decode(token, signing_key.key, algorithms=["ES256"], audience="https://api.example.com")

Связанные ошибки

Открыть всю базу ошибок подписей