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

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

no applicable key found in the JSON Web Key Set

jose (JavaScript) — JWKSNoMatchingKey, code ERR_JWKS_NO_MATCHING_KEY

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

jose просмотрела переданный ей набор ключей JSON Web Key Set и не нашла ни одного ключа, которым разрешено проверять этот токен. Ключ подходит, только если выполнены все условия: его `kid` равен `kid` из заголовка токена (если он там есть), его `kty` соответствует `alg` токена, его `alg` (если задан) равен `alg` токена, его `crv` совпадает с нужным (P-256 для ES256), `use` отсутствует или равен `"sig"`, а `key_ops` (если задан) содержит `"verify"`. Никаких криптографических операций не выполнялось — сбой произошёл при выборе ключа.

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

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

  1. 1.

    Сравните kid токена с опубликованными ключами

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

    bash
    # kid and alg the token asks for
    python3 -c 'import base64,json,sys; h=sys.argv[1].split(".")[0]; print(json.loads(base64.urlsafe_b64decode(h + "=" * (-len(h) % 4))))' "$TOKEN"
    # kid, alg, kty, crv, use of every key the issuer publishes
    curl -s https://issuer.example.com/.well-known/jwks.json | jq '.keys[] | {kid, alg, kty, crv, use}'
  2. 2.

    Загружайте JWKS издателя вместо закрепления ключей

    `createRemoteJWKSet` кеширует ключи и заново загружает набор, когда в токене указан незнакомый ему `kid`, поэтому ротации подхватываются автоматически, а произвольные ключи при этом не принимаются.

    js
    import { createRemoteJWKSet, jwtVerify } from "jose";
    
    // Fetches the JWKS, caches it, and refetches when a token names an unknown kid
    // (at most once per cooldownDuration, 30 s by default).
    const jwks = createRemoteJWKSet(new URL("https://issuer.example.com/.well-known/jwks.json"));
    const { payload } = await jwtVerify(token, jwks, {
      algorithms: ["ES256"],
      issuer: "https://issuer.example.com",
    });
  3. 3.

    Публикуйте ключи с согласованными метаданными

    Если издателем управляете вы, убедитесь, что у каждого ключа подписи уникальный `kid`, `use: "sig"`, а `alg` и `crv` соответствуют токенам, которые он подписывает. Публикуйте новый ключ до того, как начнёте им подписывать.

    json
    {
      "keys": [
        { "kty": "EC", "crv": "P-256", "kid": "2026-10", "use": "sig", "alg": "ES256",
          "x": "…", "y": "…" }
      ]
    }

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

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