Логотип Workflow

Article

Jwt Theory

Stage 9. JWT Basics

What is JSON Web Token?

JWT (JSON Web Token) — это открытый стандарт RFC 7519, который описывает компактный и самодостаточный формат передачи утверждений (claims) в виде JSON-объекта между сторонами. Доверять токену можно только после корректной проверки подписи и обязательных полей. На практике JWT подписывают либо общим секретом (HMAC), либо асимметричной парой ключей (например, RSA или ECDSA).

JWT может быть и зашифрованным, но в большинстве API-сценариев используются именно подписанные токены. Подписанный токен даёт контроль целостности: получатель может проверить, что claims не были изменены. При асимметричной подписи дополнительно подтверждается, что токен выпустила сторона, владеющая приватным ключом.

Чаще всего JWT применяют для авторизации: после логина клиент отправляет токен в следующих запросах, а API принимает решение по верифицированным claims. Второй частый сценарий — безопасный обмен данными между системами, где важно проверить источник и неизменность содержимого.

В компактном виде JWT состоит из трёх частей, разделённых точками:

header.payload.signature

Заголовок обычно содержит тип токена и алгоритм подписи:

{
  "typ": "JWT",
  "alg": "HS256"
}

Полезная нагрузка содержит claims. Обычно их делят на три группы:

  • Registered claims (iss, sub, aud, exp и другие стандартные поля).
  • Public claims (общие поля с контролем коллизий имён).
  • Private claims (кастомные поля по соглашению между системами).

Пример payload:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

JWT часто воспринимают как “безопасный по умолчанию” формат, но это опасное упрощение. JWT — это только формат сообщения. Реальная безопасность зависит от того, как токен выпускается, передаётся, валидируется и отзывается. Если эти процессы не продуманы, даже подписанный токен не защитит API от ошибок дизайна.

JWT structure

По практическим рекомендациям для production-систем ключевое правило такое: каждый сервис, который получает JWT, должен валидировать его полностью. Проверка только exp недостаточна. Нужны минимум: подпись, iss, aud, срок действия, обязательные доменные claims и тип токена. Особенно важно не путать access token и ID token. ID token предназначен клиентскому приложению, а access token — API. Когда это смешивают, появляются уязвимости и нестабильные интеграции.

Authorization: Bearer <access-token>

JWT security checklist

Отдельный риск связан с содержимым payload. JWT легко декодируется, поэтому в него нельзя помещать чувствительные данные, персональные сведения и внутренние технические детали, которые могут помочь атакующему. Если токен уходит во фронт-канал, полезно минимизировать claims и выносить пользовательские данные в отдельный API-вызов. В более строгих архитектурах используют паттерн, где внешнему клиенту выдаётся непрозрачный токен, а внутренний JWT видят только API за шлюзом.

JWT token exposure patterns

Критична валидация заголовка alg. На сервере должен быть явный allow-list допустимых алгоритмов. Deny-list здесь слабее, потому что исторически существовали обходы через регистр и нестандартные значения. Неподписанные токены (alg=none) в обычном API-потоке принимать нельзя. Для подписи в современных системах чаще рекомендуют асимметричные алгоритмы; при возможности выбирают более современные варианты вроде EdDSA или ES256, а не полагаются только на “самый привычный” вариант.

JWT почти всегда bearer-токен, а значит “кто предъявил, тот и использует”. Если модель угроз этого не допускает, токен связывают с клиентом через sender-constrained подход (например, mTLS или PoP/DPoP), чтобы украденный токен нельзя было использовать с другого клиента.

Так как JWT сложно отозвать мгновенно после выдачи, срок жизни access token должен быть коротким: обычно минуты, реже часы. Также полезно валидировать nbf и iat, а при сравнении времени учитывать небольшой clock skew (обычно секунды, не минуты). Долгоживущие токены “на недели” резко увеличивают последствия утечки.

Наконец, безопасность JWT невозможна без зрелого управления ключами: централизованное хранение, ротация, окно совместимости, аварийная замена и наблюдаемость по причинам отказа (bad_signature, wrong_issuer, wrong_audience, token_expired). JWT хорошо масштабируется только тогда, когда команда управляет им как security-платформой, а не как строкой в заголовке.

Практический сценарий

Сервис принимает токены от нескольких клиентов. Один API проверяет только подпись и exp, второй — ещё aud, третий случайно принимает ID token как access token. В итоге часть запросов проходит “как повезёт”, а часть падает с 401 без ясной причины. После унификации политики валидации (тип токена, iss, aud, claims, алгоритм, время) и общей key-rotation схемы поведение становится стабильным и предсказуемым.

Quiz

Проверьте, что вы усвоили

Авторизуйтесь чтоб пройти тесты