JWT

2 tools

Основы веб-безопасности

Веб-безопасность — это практика защиты веб-приложений и API от несанкционированного доступа, утечек данных и атак.

JSON Web Token (JWT) — доминирующий механизм аутентификации без состояния в современной веб-разработке.

JSON Web Tokens (JWT)

JWT — это компактный, URL-безопасный способ представления утверждений между двумя сторонами. Он состоит из трёх частей, закодированных в Base64url и разделённых точками.

Три части JWT

Header

Содержит метаданные токена: алгоритм подписи (alg) и тип токена (typ).

Закодировано
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Декодировано
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload

Содержит утверждения: заявления о пользователе. Данные payload НЕ шифруются, только подписываются.

Закодировано
eyJzdWIiOiJ1c2VyXzEyMyIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxNzIwMDAwMH0
Декодировано
{
  "sub": "user_123",
  "role": "admin",
  "exp": 1717200000
}
Signature

Криптографическая подпись над закодированными заголовком и payload. Верификация гарантирует, что токен не был изменён.

Закодировано
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Декодировано
HMACSHA256(
  base64url(header) + "." +
  base64url(payload),
  secret
)

Стандартные утверждения JWT

Спецификация JWT определяет стандартные имена утверждений для обеспечения совместимости:

УтверждениеНазваниеОписание
issIssuerИдентифицирует субъект, выдавший токен
subSubjectИдентифицирует субъект токена (например, ID пользователя)
audAudienceИдентифицирует получателей токена
expExpirationUnix-временная метка, после которой токен не принимается
nbfNot BeforeUnix-временная метка, до которой токен не принимается
iatIssued AtUnix-временная метка выдачи токена
jtiJWT IDУникальный идентификатор токена для предотвращения replay-атак

Алгоритмы подписи

Алгоритм подписи объявляется в заголовке JWT. Правильный выбор критически важен для безопасности:

HS256 / HS384 / HS512Симметричный (HMAC)

Использует общий секретный ключ для подписи и верификации.

Использовать когда: Внутренние сервисы, где вы контролируете все стороны.
RS256 / RS384 / RS512Асимметричный (RSA)

Использует приватный ключ для подписи и публичный для верификации. Приватный ключ никогда не покидает сервер аутентификации.

Использовать когда: Микросервисные архитектуры, верификация токенов третьих сторон, OAuth2 и OpenID Connect.
ES256 / ES384 / ES512Асимметричный (ECDSA)

Как RSA, но с меньшими ключами и более быстрой подписью.

Использовать когда: Мобильные и IoT-приложения, где важна производительность.
"alg": "none"Без подписи — ОПАСНО

Нет подписи. Токен с alg:none не имеет гарантий целостности и может быть подделан.

Использовать когда: Никогда не использовать в продакшене.

Потоки аутентификации

Password Grant (прямой)
  1. 1.Пользователь отправляет имя пользователя и пароль на endpoint входа
  2. 2.Сервер проверяет учётные данные по базе данных пользователей
  3. 3.Сервер подписывает JWT с утверждениями пользователя и сроком действия
  4. 4.Клиент сохраняет JWT (localStorage, cookie или память)
  5. 5.Клиент отправляет JWT в заголовке Authorization: Bearer для последующих запросов
Authorization Code + PKCE (OAuth2)
  1. 1.Клиент перенаправляет пользователя на сервер авторизации с code challenge
  2. 2.Пользователь аутентифицируется и авторизует клиентское приложение
  3. 3.Сервер авторизации перенаправляет с одноразовым кодом авторизации
  4. 4.Клиент обменивает код + верификатор на access и refresh токены
  5. 5.Клиент использует access token для API-вызовов; refresh token для обновления

Распространённые уязвимости JWT

JWT безопасны при правильной реализации. Вот наиболее распространённые ошибки реализации:

Путаница алгоритмов (alg:none)Критический

Некоторые библиотеки принимают токены с alg:none. Злоумышленник может изменить payload и подделать любой JWT.

Путаница HS256/RS256Критический

Если библиотека должна верифицировать RS256, но принимает HS256, злоумышленник может подписать токен, используя публичный ключ как HMAC-секрет.

Отсутствует проверка срока действияВысокий

JWT без утверждения exp позволяет использовать токены неограниченно. Всегда устанавливайте короткий срок действия.

Чувствительные данные в payloadВысокий

Payload JWT закодирован в Base64, а не зашифрован. Никогда не храните пароли или другие секреты в утверждениях JWT.

Слабые секретные ключи (HS256)Средний

JWT, подписанные с короткими или предсказуемыми секретами, могут быть взломаны методом перебора.

Отсутствует верификация подписиСредний

Принятие JWT без верификации подписи полностью доверяет payload. Всегда верифицируйте подпись перед доверием любому утверждению.

Часто задаваемые вопросы

Зашифрованы ли JWT?

Стандартные JWT (JWS) подписаны, но НЕ зашифрованы. Payload закодирован в Base64url, что тривиально обратимо.

Как долго должен быть действителен JWT?

Access токены должны быть кратковременными: 5–60 минут — типичное значение. Используйте refresh токены для получения новых.

Где хранить JWT в браузере?

HttpOnly cookies — наиболее безопасный вариант, недоступный для JavaScript и защищающий от XSS.

Можно ли отозвать JWT до истечения срока?

Нет без серверного состояния. Решения: короткий срок действия, список блокировки токенов (Redis).

В чём разница между JWT и session cookies?

Session cookies хранят случайный ID сессии; сервер ищет данные сессии. JWT самодостаточны — сервер проверяет подпись без обращения к базе данных.

Какие утверждения включать в JWT?

Минимум: sub (ID пользователя), exp (срок действия) и iat (время выдачи). Держите payload небольшим.

RS256 лучше HS256?

RS256 (асимметричный) лучше для большинства продакшен-систем, поскольку только сервер аутентификации нуждается в приватном ключе.

Что такое PKCE и почему это важно?

PKCE — расширение потока авторизационного кода OAuth2, предотвращающее перехват кода. Обязательно для публичных клиентов (SPA, мобильные приложения).