JOSEAlgNotAllowed и JOSENotSupported

Ошибка возникает в библиотеке JOSE при попытке использования криптографического алгоритма, который явно запрещён политикой приложения или не входит в список разрешённых алгоритмов при верификации или шифровании токенов. В экосистеме JOSE (JSON Object Signing and Encryption) контроль алгоритмов является одним из ключевых механизмов безопасности, так как именно через выбор слабого или устаревшего алгоритма чаще всего происходят криптографические атаки.

В библиотеке jose (современная реализация для Node.js и браузера) эта ошибка появляется в момент, когда вызываемый алгоритм не соответствует ограничениям, заданным разработчиком через конфигурацию или контекст проверки токена.

Причины возникновения JOSEAlgNotAllowed

Основные сценарии:

  • использование алгоритма, не включённого в allow-list (например, HS256 запрещён, но токен подписан им)
  • попытка проверки JWT с алгоритмом, который отличается от ожидаемого
  • несоответствие политики безопасности организации (например, разрешены только EdDSA или RS256)
  • получение токена из внешнего источника с неподдерживаемым алгоритмом
  • явное ограничение алгоритмов через параметры algorithms при верификации

В современных реализациях jose разработчик часто задаёт список допустимых алгоритмов вручную:

import { jwtVerify } from 'jose'

await jwtVerify(token, key, {
  algorithms: ['RS256', 'ES256']
})

Если токен будет подписан, например, HS256, будет выброшена ошибка, эквивалентная JOSEAlgNotAllowed.

Логика работы ограничения алгоритмов

С точки зрения архитектуры JOSE, алгоритм — это часть защищённого заголовка JWT:

{
  "alg": "HS256",
  "typ": "JWT"
}

При верификации библиотека выполняет строгую проверку:

  1. извлекает alg из заголовка токена
  2. сравнивает его с разрешённым списком
  3. при несоответствии прерывает выполнение
  4. выбрасывает JOSEAlgNotAllowed

Это предотвращает атаки класса “alg confusion”, когда злоумышленник подменяет алгоритм подписи на более слабый или вообще на симметричный.

Практический пример возникновения

import { jwtVerify } from 'jose'

const key = new TextEncoder().encode('secret')

await jwtVerify(token, key, {
  algorithms: ['RS256']
})

Если token подписан как:

{ "alg": "HS256" }

результатом будет ошибка JOSEAlgNotAllowed.

Рекомендации по устранению

  • всегда явно задавать список допустимых алгоритмов
  • не использовать wildcard-подходы без необходимости
  • разделять алгоритмы по типам ключей (RSA, EC, HMAC)
  • проверять alg до выполнения криптографических операций
  • избегать доверия к внешним токенам без валидации политики

JOSENotSupported

Ошибка JOSENotSupported возникает, когда библиотека JOSE сталкивается с операцией, которая не поддерживается текущей средой выполнения, криптографическим провайдером или версией реализации.

В отличие от JOSEAlgNotAllowed, которая связана с политикой безопасности, JOSENotSupported указывает на техническую невозможность выполнения операции.

Основные причины возникновения JOSENotSupported

  • отсутствие поддержки алгоритма в WebCrypto API
  • использование алгоритма, который не реализован в текущей версии jose
  • запуск в окружении с ограниченной криптографией (например, старые версии Node.js или браузеры без полного WebCrypto)
  • попытка использовать операции JWE/JWS, не поддерживаемые платформой
  • несовместимость ключевого типа и алгоритма (например, RSA ключ с EC алгоритмом)

Типичный сценарий

import { SignJWT } from 'jose'

await new SignJWT({ sub: '123' })
  .setProtectedHeader({ alg: 'EdDSA' })
  .sign(privateKey)

Если среда не поддерживает EdDSA, будет выброшена ошибка JOSENotSupported.

Связь с WebCrypto API

Современная версия jose активно использует WebCrypto:

  • в браузере: window.crypto.subtle
  • в Node.js: crypto.webcrypto.subtle

Если нужная операция отсутствует в реализации, возникает ошибка поддержки.

Пример ограничений:

  • некоторые версии Node.js не поддерживают Ed25519
  • старые браузеры не поддерживают RSA-PSS
  • ограниченные среды (edge runtime, sandbox) блокируют часть операций

Несовместимость алгоритма и ключа

Частый источник ошибки:

  • алгоритм требует EC-ключ
  • передан RSA-ключ
  • или наоборот

Пример:

await jwtVerify(token, rsaPublicKey, {
  algorithms: ['ES256']
})

Здесь ожидается EC-ключ, но передан RSA, что приводит к JOSENotSupported.

Влияние формата ключей

JOSE строго разделяет типы ключей:

  • RSA (RS256, PS256)
  • EC (ES256, ES384)
  • OKP (EdDSA)

Неверная комбинация приводит к невозможности выполнения криптографической операции.

Диагностика ошибки

При появлении JOSENotSupported важно проверить:

  • версию Node.js (>= 16/18/20 для современных алгоритмов)
  • наличие WebCrypto
  • формат ключа (JWK, PEM, CryptoKey)
  • поддерживаемость алгоритма в спецификации среды
  • корректность импорта ключа через importKey или importPKCS8

Пример проверки среды

import { generateKeyPair } from 'jose'

const { publicKey, privateKey } = await generateKeyPair('RS256')

Если генерация или использование ключа падает, значит окружение не поддерживает алгоритм.

Различие между JOSEAlgNotAllowed и JOSENotSupported

  • JOSEAlgNotAllowed — алгоритм запрещён политикой приложения
  • JOSENotSupported — алгоритм или операция технически невозможны в текущей среде

Первый связан с безопасностью, второй — с ограничениями реализации.

Практическая стратегия обработки

  • проверять поддержку алгоритмов при старте приложения
  • формировать whitelist с учётом среды выполнения
  • использовать fallback-алгоритмы (например, RS256 вместо EdDSA в старых окружениях)
  • валидировать ключи до криптографических операций
  • централизовать работу с JOSE через единый модуль

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