← Все статьи

JWT в Node.js: пять ошибок, которые ломают API

Base64 — не шифрование, alg=none, слабый secret и refresh без ротации: чеклист перед продом JWT-авторизации.

Содержание

Коротко

JWT в Node.js часто внедряют «по туториалу»: кладут данные в payload, ставят длинный TTL и заявно считают токен «зашифрованным». На Dev.to разбирают типичные ошибки — от CPF в payload до refresh без ротации — и дают рабочую схему access + refresh.

Что произошло

Автор начинает с реального кейса: разработчик положил CPF и хеш пароля в JWT, считая Base64 защитой. Ревьюер отклонил PR — и это не редкость.

JWT — это подпись, не шифрование: header + payload + signature. Любой, кто получил токен, читает payload. Безопасность держится на секрете/ключе и проверке подписи, а не на «скрытости» данных.

Пять частых провалов из материала:

Ошибка Риск Что делать
Секреты в payload Утечка PII при XSS/логах Только идентификаторы; чувствительное — в БД
alg: none Подмена алгоритма, обход проверки Явный allowlist алгоритмов в verify
Слабый secret Brute-force подписи ≥256 бит, env/vault, ротация
Без exp Вечный access-токен Короткий TTL access (минуты)
Нет aud/iss Токен «чужого» сервиса принимается Проверять issuer и audience в мультисервисе

Отдельный блок — refresh tokens: хранить в БД, ротировать при каждом обновлении, вести family ID и отзывать всё семейство при компрометации одного refresh.

Почему это важно

Express/Fastify/Nest-проекты часто получают auth «из npm-пакета за вечер». JWT кажется простым, но ошибки не видны в unit-тестах — их находят pentest, утечка логов или баг в middleware.

Refresh без ротации превращает украденный refresh в долгоживущий ключ ко всему аккаунту. А payload с email/ролями/PII — подарок для атакующего при любом XSS.

На практике

  1. Access — 5–15 минут; refresh — дни/недели, только httpOnly + Secure + SameSite cookie или отдельный endpoint с жёсткой rate limit.
  2. В jwt.verify явно указать algorithms: ['HS256'] (или RS256) — не доверять header от клиента.
  3. Payload: sub, roles/scope, jti — без паролей, документов, payment data.
  4. Refresh: одноразовое использование + запись в БД; при повторном use того же refresh — revoke family.
  5. Перед продом — чеклист: secret из vault, exp/nbf, aud/iss для микросервисов, не логировать Authorization.

Итог

JWT удобен как stateless bearer между сервисами, но только при дисциплине: короткий access, ротация refresh, никаких секретов в payload и жёсткая verify-конфигурация. Материал на Dev.to — хороший pre-release чеклист для Node API.