Перейти к содержимому
ecdsa.com
Node.js

jsonwebtoken (Node.js)

jsonwebtoken от Auth0 — самый устанавливаемый пакет JWT для Node.js: токены HMAC, RSA и ECDSA поверх node:crypto и, начиная с версии 9, проверка алгоритма с привязкой к типу ключа — но без EdDSA.
Лицензия
MIT
Проверенная версия
9.0.3 ·
Исходный код
github.com/auth0/node-jsonwebtoken
Документация
github.com/auth0/node-jsonwebtoken#readme

Совместимость вкратце

JOSE и JWT

Алгоритмы JWS
HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512

jsonwebtoken подписывает и проверяет JSON Web Token тремя вызовами: jwt.sign(), jwt.verify() и jwt.decode(). Уровень JWS он обрабатывает через пакеты jws и jwa, а криптографию выполняет с помощью node:crypto, поэтому ключами могут быть строки PEM, буферы или экземпляры KeyObject. jwt.decode() только разбирает токен — подпись он никогда не проверяет, и код, который читает из него утверждения, доверяет всему, что написал отправитель.

Версия 9 закрыла классические пути для подмены алгоритма, и проверка подтвердила это для 9.0.3: без параметра algorithms список разрешённых алгоритмов определяется типом ключа, токен HS256, подписанный текстом открытого ключа, отклоняется, а alg: none проходит, только если указать none в списке и вообще не передавать ключ. И всё же передавайте algorithms: этот параметр документирует контракт и продолжит работать, если тип ключа когда-нибудь изменится.

Список алгоритмов ограничен набором RFC 7518: EdDSA, Ed25519 и ES256K нет. Токен от издателя, который подписывает Ed25519 (это обычное дело для jose, а также для стеков на Go и Rust), здесь проверить нельзя; используйте вместо этого jose. ES256 также требует ключ P-256, и при попытке подписать под этим именем ключом P-384 библиотека выбрасывает исключение, а не создаёт токен, который отклонили бы другие библиотеки.

Подписи ECDSA внутри токена — это 64-байтовый формат raw r‖s, который предписывает JWS. Если токен собран вручную из вывода openssl dgst, SHA256withECDSA из Java или облачного KMS, его подпись закодирована в DER и проверка завершается ошибкой "ES256" signatures must be "64" bytes: вставьте токен в отладчик JWT, чтобы увидеть длину подписи, и исправьте подпись с помощью конвертера DER ⇄ raw.

Две настройки по умолчанию ведут себя не так, как предполагают многие команды: одна строже, другая мягче. clockTolerance равен нулю, поэтому расхождение часов между серверами в несколько секунд уже приводит к ошибке jwt expired, а exp необязателен, поэтому срок действия токена, выпущенного без него, никогда не истекает. Задавайте expiresIn при подписи и maxAge или явное требование exp при проверке; секреты HMAC проверяйте инструментом проверки секретов JWT.

Факты и проверки, на которых они основаны

Ничего из приведённого ниже не скопировано из документации. 20 октября 2026 г. проверка content/libraries/verify/jsonwebtoken/run.sh запустила jsonwebtoken (Node.js) 9.0.3 в среде Node.js 24.22.0 в образе контейнера node:24.22.0-bookworm-slim; содержимое страницы должно совпадать с выводом проверки, а у каждого факта приведены соответствующие строки вывода.

  • Алгоритмы JWS

    HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512

    HS256/384/512, RS256/384/512, PS256/384/512 и ES256/384/512: в ходе проверки подпись и проверка подписи прошли успешно. EdDSA, Ed25519, Ed448, ES256K и ML-DSA были отклонены при подписи.

    Что записала проверка
    fact jws-algorithms = HS256, HS384, HS512, RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512
    evidence jws-algorithms: ES256K: sign throws Error: "algorithm" must be a valid string enum value
    evidence jws-algorithms: EdDSA: sign throws Error: "algorithm" must be a valid string enum value
    evidence jws-algorithms: Ed25519: sign throws Error: "algorithm" must be a valid string enum value
    evidence jws-algorithms: Ed448: sign throws Error: "algorithm" must be a valid string enum value
    evidence jws-algorithms: ML-DSA-44: sign throws Error: "algorithm" must be a valid string enum value
  • Кодировка подписи ES256

    raw

    Подписи ES256 в токене — 64 байта в формате raw r‖s, как требует RFC 7518; библиотека преобразует их из DER, который выдаёт node:crypto.

    Что записала проверка
    fact jws-ecdsa-encoding = raw
  • Подпись в DER внутри JWS

    rejected

    Токен, подпись ES256 которого перекодировали в DER, не проходит проверку с ошибкой "ES256" signatures must be "64" bytes, saw "72" (это число — длина блока DER).

    Что записала проверка
    fact jws-der-signature = rejected
    evidence jws-der-signature: TypeError: "ES256" signatures must be "64" bytes, saw "72"
  • Список разрешённых алгоритмов

    from-key

    Без algorithms при проверке допускаются только алгоритмы, подходящие к ключу: токен HS256 прошёл проверку с общим секретом, токен ES256 — с открытым ключом EC, а проверка токена RS256 ключом EC завершилась ошибкой invalid algorithm.

    Что записала проверка
    fact jwt-algorithm-allowlist = from-key
    evidence jwt-algorithm-allowlist: RS256 token against an EC key: JsonWebTokenError: invalid algorithm
  • Неподписанные токены (alg none)

    opt-in

    Неподписанный токен отклоняется с ошибкой jwt signature is required всякий раз, когда передан ключ; проверку он проходит, только если algorithms содержит none, а аргумент ключа пуст.

    Что записала проверка
    fact jwt-alg-none = opt-in
    evidence jwt-alg-none: with a key: JsonWebTokenError: jwt signature is required
    evidence jwt-alg-none: algorithms ["none"] and no key: verified
  • Открытый ключ в роли секрета HMAC

    rejected

    Токен HS256, ключом HMAC для которого служит текст PEM открытого ключа, отклонён как без списка алгоритмов (invalid algorithm), так и с algorithms: ["HS256"] (secretOrPublicKey must be a symmetric key when using HS256).

    Что записала проверка
    fact jwt-hmac-public-key = rejected
    evidence jwt-hmac-public-key: no list: JsonWebTokenError: invalid algorithm
    evidence jwt-hmac-public-key: algorithms ["HS256"]: JsonWebTokenError: secretOrPublicKey must be a symmetric key when using HS256
  • Сверка кривой с alg

    enforced

    При подписи ES256 ключом P-384 выбрасывается "alg" parameter "ES256" requires curve "prime256v1". — ES256, ES384 и ES512 привязаны к кривым P-256, P-384 и P-521.

    Что записала проверка
    fact jwt-ecdsa-curve-check = enforced
    evidence jwt-ecdsa-curve-check: Error: "alg" parameter "ES256" requires curve "prime256v1".
  • Допустимое расхождение часов по умолчанию

    0s

    По умолчанию расхождение часов не допускается: токен, срок действия которого истёк 3 секунды назад, отклонён. Чтобы учесть расхождение, задайте clockTolerance в секундах.

    Что записала проверка
    fact jwt-clock-skew = 0s
  • Обязательное утверждение о сроке действия

    no

    Токен без утверждения exp успешно прошёл проверку; срок действия проверяется, только если это утверждение есть в токене или задан maxAge.

    Что записала проверка
    fact jwt-exp-required = no

Использование

Выпустите и проверьте токен ES256, зафиксировав на стороне проверки алгоритм, издателя и аудиторию.
import { generateKeyPairSync } from "node:crypto";
import jwt from "jsonwebtoken";

const { privateKey, publicKey } = generateKeyPairSync("ec", { namedCurve: "P-256" });

const token = jwt.sign({ sub: "user-42" }, privateKey, {
  algorithm: "ES256",
  expiresIn: "10m",
  issuer: "https://auth.example.com",
  audience: "api",
});

// Pin the algorithm, issuer and audience instead of trusting the token header.
const claims = jwt.verify(token, publicKey, {
  algorithms: ["ES256"],
  issuer: "https://auth.example.com",
  audience: "api",
});

console.log("sub:", claims.sub);

Тестовый стенд для фрагментов кода запускает каждый пример без изменений в образе контейнера node:24.22.0-bookworm-slim, и запуск завершается ошибкой, если вывод не совпадает.

Подготовка
npm init -y >/dev/null && npm install --no-audit --no-fund jsonwebtoken@9.0.3
Команда
node usage.mjs
Вывод должен совпадать (регулярное выражение)
sub: user-42

Библиотеки