Сообщение об ошибке
Key for the ES256 algorithm must be one of type CryptoKey, KeyObject, or JSON Web Key.
Также выводится как
- Key for the RS256 algorithm must be one of type CryptoKey, KeyObject, or JSON Web Key.
- Key for the HS256 algorithm must be one of type CryptoKey, KeyObject, JSON Web Key, or Uint8Array.
Алгоритм в тексте сообщения берётся из вашего токена (`ES256`, `RS256`, `EdDSA`…). Для алгоритмов HMAC список заканчивается словами «or Uint8Array».
jose (JavaScript) — TypeError from jwtVerify / SignJWT.sign
Что это означает
Вы передали jose значение, которое она не может использовать как ключ. Чаще всего это PEM-строка или секрет в виде обычной строки. Начиная с версии 4, jose принимает только объекты ключей: `CryptoKey` из WebCrypto, `KeyObject` из Node.js, объект JWK или (для алгоритмов HMAC) `Uint8Array`. Текстовые форматы сначала нужно импортировать: jose никогда не угадывает, что содержит строка.
Почему это происходит
PEM-строку передали напрямую
частоКод, перенесённый с библиотеки jsonwebtoken, которая принимает PEM-текст, часто передаёт `process.env.PUBLIC_KEY` прямо в `jwtVerify`. jose требует сначала вызвать `importSPKI` (для открытых ключей), `importPKCS8` (для закрытых ключей) или `importX509` (для сертификатов).
Секрет HMAC передали строкой
частоДля HS256/HS384/HS512 секрет должен быть массивом байтов: `new TextEncoder().encode(secret)`. Строка как таковая отклоняется, даже если это правильный секрет.
Строка с URL JWKS вместо функции набора ключей
иногда`"https://issuer/.well-known/jwks.json"` — это строка, а не ключ. Оберните её в `createRemoteJWKSet(new URL(...))`: эта функция возвращает функцию, которую ожидает `jwtVerify`.
Значение конфигурации не задано
иногдаНезаданная переменная окружения возвращает `undefined`, и это значение не проходит ту же проверку типа. Проверяйте конфигурацию при запуске, чтобы вместо этого ошибка называла отсутствующую переменную.
Как исправить
- 1.
Импортируйте PEM-ключи один раз при запуске
`importSPKI` и `importPKCS8` принимают PEM-текст и алгоритм, с которым будет использоваться ключ, и возвращают `CryptoKey`, пригодный для повторного использования во всех запросах.
js import { importSPKI, importPKCS8, jwtVerify } from "jose"; const publicKey = await importSPKI(process.env.JWT_PUBLIC_KEY_PEM, "ES256"); // -----BEGIN PUBLIC KEY----- await jwtVerify(token, publicKey, { algorithms: ["ES256"] }); const privateKey = await importPKCS8(process.env.JWT_PRIVATE_KEY_PEM, "ES256"); // -----BEGIN PRIVATE KEY----- - 2.
Преобразуйте секреты HMAC в байты
Для HS256 используйте случайный секрет длиной не менее 32 байт и передавайте его как `Uint8Array`. Если секрет хранится в кодировке base64, декодируйте его в байты, а не кодируйте сам base64-текст.
js import { jwtVerify } from "jose"; const secret = new TextEncoder().encode(process.env.JWT_SECRET); // 32+ random bytes for HS256 await jwtVerify(token, secret, { algorithms: ["HS256"] }); - 3.
Проверяйте по набору ключей, а не по URL
Для токенов от поставщика удостоверений передавайте функцию, которую возвращает `createRemoteJWKSet`; тогда jose выбирает ключ по `kid` для каждого токена.
js import { createRemoteJWKSet, jwtVerify } from "jose"; const jwks = createRemoteJWKSet(new URL("https://issuer.example.com/.well-known/jwks.json")); await jwtVerify(token, jwks, { algorithms: ["ES256"] });