Сообщение об ошибке
jwt signature is required
jsonwebtoken (Node.js) — JsonWebTokenError from jwt.verify()
Что это означает
Третий сегмент токена пуст: это незащищённый JWT (`alg: "none"`) или подписанный токен с обрезанной подписью. Но вы вызвали `verify()` с ключом, а значит, подпись обязательна. jsonwebtoken отказывается принимать утверждения, которые никто не подписывал. Если такие токены приходят в ваш API извне, возможно, кто-то проверяет, подвержен ли он классической уязвимости «alg none».
Почему это происходит
Незащищённый токен с alg «none»
частоRFC 7519 допускает неподписанные JWT там, где целостность гарантирована другими средствами; API к таким случаям никогда не относится. Токен вроде `eyJhbGciOiJub25lIn0.eyJzdWIiOiJhZG1pbiJ9.` может выдавать себя за кого угодно.
Токены, собранные вручную в тестах или инструментах
иногдаПустая подпись у фикстур, собранных кодированием заголовка и полезной нагрузки в base64, и у токенов из отладочных инструментов, в которых отключено подписывание.
Подпись обрезали при передаче
иногдаЕсли фильтр маскирования данных в логах, ограничение длины URL или столбец в хранилище обрезали токен сразу после второй точки, остаются корректные на вид заголовок и полезная нагрузка, но проверять нечего.
Как исправить
- 1.
Сохраните отказ и список разрешённых алгоритмов
Проверяйте токены с явным списком `algorithms`, в котором есть только те алгоритмы, которые использует ваш издатель. Если неподписанные токены приходят извне, записывайте в лог источник запроса; не добавляйте ветку кода, которая их принимает.
js // Always pass an explicit allow-list; "none" must never be in it. const claims = jwt.verify(token, publicKey, { algorithms: ["ES256"] }); - 2.
Подписывайте тестовые токены одноразовым ключом
Генерируйте пару ключей при подготовке тестов и подписывайте ею фикстуры, чтобы тесты проходили тот же путь проверки, что и в рабочей среде.
js import { generateKeyPairSync } from "node:crypto"; // Test setup: a throwaway key pair, real signatures, same verification path as production. const { privateKey, publicKey } = generateKeyPairSync("ec", { namedCurve: "P-256" }); const token = jwt.sign({ sub: "test-user" }, privateKey, { algorithm: "ES256", expiresIn: "5m" });