Что такое JWT (JSON Web Token) и как он работает?

Ответ

JWT (JSON Web Token) — это открытый стандарт (RFC 7519) для создания токенов доступа, которые безопасно передают информацию между сторонами в виде компактного JSON-объекта.

Структура токена (3 части, разделенные точками):

  1. Header (alg, typ): Определяет алгоритм подписи (например, HS256) и тип токена.
  2. Payload (claims): Содержит утверждения (claims) — данные о пользователе (например, user_id, roles, exp — срок действия).
  3. Signature: Создается путем кодирования header и payload, их объединения и подписи секретным ключом (HMAC) или приватным ключом (RSA). Подпись верифицирует отправителя и гарантирует целостность данных.

Пример декодированного JWT:

// HEADER: ALGORITHM & TOKEN TYPE
{
  "alg": "HS256",
  "typ": "JWT"
}

// PAYLOAD: DATA
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622
}

// SIGNATURE: HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

Типичный flow аутентификации:

  1. Пользователь логинится, сервер проверяет учетные данные.
  2. Сервер генерирует JWT и отправляет его клиенту.
  3. Клиент включает JWT в заголовок Authorization: Bearer <token> последующих запросов.
  4. Сервер проверяет подпись и exp в токене, предоставляет доступ к ресурсам.

Преимущества для тестирования безопасности:

  • Stateless: Серверу не нужно хранить сессию, что упрощает масштабирование.
  • Самостоятельный (self-contained): В токене есть все необходимые данные.
  • Уязвимости для проверки: Срок действия токена (exp), надежность алгоритма подписи, хранение на клиенте (не в localStorage для предотвращения XSS).
  • Недостаток: Сложность отзыва до выпуска срока действия (решается короткоживущими токенами и refresh-токенами).

Ответ 18+ 🔞

А, слушай, JWT, ёпта! Это ж та самая хуйня, которую везде сейчас суют, как горячие пирожки в рот. Ну, типа, открытый стандарт, бумажка RFC 7519, но если по-русски — это просто способ слепить такую цифровую бумажку-пропуск, в которую запихнули кучу инфы в формате JSON.

Представь, блядь, три куска, склеенные точками, как бусины на нитке, только вместо бусин — зашифрованная херня.

Первая часть — голова (Header). Там два главных пацана сидят: alg и typ. alg — это алгоритм, которым эту хрень подписали, типа HS256. А typ — просто кричит всем: «Я JWT, блядь, не перепутайте меня с каким-нибудь купоном на скидку!»

Вторая часть — тело (Payload), оно же claims. Вот тут-то и живут все секретики. user_id, роли, дата создания (iat), и самое главное — срок годности, exp. Это как дата на молоке, просрочился — выкидывай нахуй, иначе отравишься. Вся суть в этих claims, они и есть полезная нагрузка, ради которой весь сыр-бор.

Третья часть — подпись (Signature). А вот это, сука, самое важное! Берутся первые две части (голову и тело), кодируются в base64, склеиваются точкой, а потом этот гибрид подписывается либо секретным ключом (если алгоритм типа HMAC), либо приватным ключом (если RSA). Эта подпись — как печать на паспорте. Она кричит: «Да, я, блядь, настоящий! Меня выпустил легитимный сервер, и меня по дороге никто не подменил!» Без неё токен — просто кусок бумаги, на котором можно писать что угодно.

Вот, смотри, как эта штука изнутри выглядит, если её разобрать:

// HEADER: ЧТО ЗА АЛГОРИТМ И ТИП
{
  "alg": "HS256",
  "typ": "JWT"
}

// PAYLOAD: САМА ИНФА, КОТОРУЮ ВЕЗЁМ
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622
}

// SIGNATURE: А ВОТ ТУТ МАГИЯ, ПОДПИСЬ ВСЕГО ЭТОГО ДОБРА

Как эта песня обычно играет на практике:

  1. Человек приходит, логинится, вводит пароль. Сервер смотрит: «А, ну окей, проходи».
  2. Сервер, не долго думая, быстренько генерит этот самый JWT и суёт его клиенту в лапы. «Держи, браток, твой пропуск».
  3. Дальше клиент, не будь дурак, при каждом следующем запросе тычет этот токен серверу под нос. Точнее, в заголовок Authorization: Bearer <token>. «Смотри, я свой, вот мой паспорт!»
  4. Сервер берёт токен, первым делом смотрит на подпись — не подделка ли? Потом глазами на exp — не просрочен ли? Если всё чисто, говорит: «Проходи, товарищ, вот тебе доступ к нашим секретным данным».

И почему все так обожают эту хуйню, особенно когда речь про безопасность?

  • Stateless (без состояния): Серверу не нужно, блядь, помнить каждый токен, как с сессиями. Он проверил подпись — и всё, свободен. Масштабируется проще простого, хоть на сто серверов раскидывай.
  • Самостоятельный (self-contained): Всё, что надо, уже внутри него лежит. Не надо бегать в базу данных каждый раз, как дурень, проверять.
  • Уязвимости, которые так весело искать: А вот тут, ёпта, начинается самое интересное! Срок действия (exp) стоит ли? Алгоритм подписи не слабенький ли? А клиент, дурак, не пихает ли его в localStorage, где любой XSS-скрипт его спиздит? Поля для головомойки — овердохуища!
  • Но есть и косяк, мать его: Отозвать этот токен досрочно — та ещё задачка. Пока срок не вышел, он живёт своей жизнью. Поэтому умные дяди придумали схему с короткоживущими access-токенами и долгоживущими refresh-токенами. Но это уже другая история, в рот меня чих-пых!