Как работает JWT-авторизация и из чего состоит токен?

Ответ

JWT (JSON Web Token) — это компактный, URL-безопасный способ представления утверждений, которые должны быть переданы между сторонами. Он часто используется для авторизации и аутентификации в распределенных системах, так как является stateless (не требует хранения сессий на сервере).

Структура JWT:

JWT состоит из трех частей, разделенных точками (.): Header.Payload.Signature.

  1. Header (Заголовок): JSON-объект, содержащий метаданные о токене, такие как тип токена (typ) и используемый алгоритм подписи (alg).

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

    Затем кодируется в Base64Url.

  2. Payload (Полезная нагрузка): JSON-объект, содержащий утверждения (claims) — информацию о пользователе или другие данные. Стандартные утверждения включают iss (издатель), exp (срок действия), sub (субъект), aud (аудитория). Можно добавлять и кастомные утверждения.

    {
      "user_id": 123,
      "username": "john.doe",
      "exp": 1735689600, // Срок действия токена (Unix timestamp)
      "role": "admin"
    }

    Также кодируется в Base64Url.

  3. Signature (Подпись): Создается путем хеширования закодированных Header и Payload вместе с секретным ключом сервера. Подпись обеспечивает целостность токена (данные не были изменены) и аутентичность (токен был выдан легитимным сервером).

    HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key)

Как работает JWT-авторизация:

  1. Аутентификация: Клиент отправляет учетные данные (логин/пароль) на сервер.
  2. Выдача токена: Сервер проверяет учетные данные. В случае успеха, он генерирует JWT, подписывает его своим секретным ключом и отправляет клиенту.
  3. Хранение токена: Клиент сохраняет полученный JWT (например, в localStorage, sessionStorage или httpOnly cookie).
  4. Авторизация: При каждом последующем запросе к защищенным ресурсам клиент прикрепляет JWT в заголовок Authorization: Bearer <token>.
  5. Валидация токена: Сервер получает запрос, извлекает JWT, проверяет его подпись с помощью своего секретного ключа. Если подпись валидна и токен не истек, сервер доверяет данным в Payload и предоставляет доступ к ресурсу.

Преимущества JWT:

  • Stateless: Серверу не нужно хранить информацию о сессиях, что упрощает масштабирование и работу с микросервисами.
  • Компактность: Токены небольшие и легко передаются.
  • Мобильность: Идеально подходят для мобильных приложений и SPA.

Недостатки и их решения:

  • Невозможность отзыва: Токен нельзя отозвать до истечения срока действия (exp).
    • Решение: Использовать короткоживущие токены в сочетании с refresh-токенами; вести "черные списки" (blacklist) отозванных токенов на сервере.
  • Уязвимость к XSS: Если токен хранится в localStorage, он может быть украден через XSS-атаки.
    • Решение: Хранить токены в httpOnly cookies (защищает от JavaScript-доступа) или использовать более сложные механизмы, такие как CSRF-токены в сочетании с JWT.

Ответ 18+ 🔞

А, JWT, ёпта, ну это ж классика, блядь! Все эти ваши авторизации-аутентификации, а по факту — просто бумажка, которую ты носишь с собой и показываешь, как пропуск на завод, только цифровая, блядь.

Смотри, как оно устроено, это чудо. Токен этот — он как бутерброд из трёх слоёв, склеенных точкой. Голова.Начинка.Подпись. Всё, пиздец, просто.

Голова (Header) — это как этикетка на консервах. Там написано, что внутри и как это проверить. Типа: «Содержимое: токен. Способ проверки: подпись HMACSHA256». Всё это в JSON, потом в Base64 — и готово, блядь.

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

Начинка (Payload) — вот тут самое интересное, блядь! Это же все твои секретики, которые сервер в тебя запихнул. Кто ты (user_id), как звать, когда срок годности истекает (exp) и, главное, кто ты по жизни — "role": "admin" или "role": "пиздюк обыкновенный". Тоже JSON, тоже Base64.

{
  "user_id": 123,
  "username": "john.doe",
  "exp": 1735689600,
  "role": "admin"
}

А теперь, блядь, подпись (Signature) — вот где магия, а точнее, ебаный криптографический фокус! Берёшь закодированные голову и начинку, склеиваешь точкой, берёшь секретный ключ (который только у сервера в сейфе, блядь!) и это всё дело хешируешь по алгоритму из головы. Получается этакая цифровая печать. Если кто-то попробует в начинке "role": "god" исправить, не зная ключа — подпись не сойдётся, и его, пидораса, нахуй выставят!

Как вся эта карусель крутится:

  1. Ты лезешь на сервер с логином-паролем, типа «я свой, впусти».
  2. Сервер проверяет, не мудак ли ты. Если нет — он тебе печатает этот самый JWT, ставит свою волшебную подпись и выдаёт, как мандат.
  3. Ты этот мандат прячешь куда подальше — в хранилище браузера или, что умнее, в httpOnly куку, чтобы какие-то левые скрипты его не сцапали.
  4. Дальше ты с этим токеном ходишь, как важная шишка. Хочешь к защищённому апи — прицепляешь в заголовок: Authorization: Bearer <твой_токен>. Мол, «смотрите, пропуск, всё законно!».
  5. Сервер, получив это, делает обратный финт: расшифровывает Base64, смотрит на подпись, проверяет её своим секретным ключом. Если всё чисто и срок не вышел — тебе зелёный свет. Всё, блядь! Никаких сессий на сервере, он тебе доверяет, как родному.

Чем это, блядь, хорошо:

  • Бессерверность (Stateless): Серверу похуй, он тебя не помнит. Ты предъявил валидную бумажку — иди, гуляй. Масштабируется на раз-два.
  • Компактность: Не раздутая хуйня, передавать легко.
  • Универсальность: И в вебе, и в мобилках — везде сойдёт.

А где, сука, подводные ебли:

  • Не отзовёшь, блядь! Выдал токен со сроком на неделю — и всё, он будет жив, даже если пользователя уже забанили. Как чека на предъявителя, ёпта.
    • Что делать? Либо делать сроки жизни короткими, как у майского жука, и выдавать refresh-токены для обновления. Либо заводить чёрный список отозванных токенов, но это уже statefulness подкрадывается, сука!
  • Уязвимость к XSS: Если хранишь токен в localStorage, то какой-нибудь ебучий скрипт-вирус может его вытащить и притворяться тобой. Пиздец и развод.
    • Что делать? httpOnly куки — наш бро. Они от скриптов спрятаны. Но тогда надо с CSRF-атаками бороться, потому что куки сами летят на сервер. Ёперный театр, одно лечим — другое калечим!

Вот и вся философия, блядь. Удобная штука, но если без мозгов использовать — сами себе яму выроете, в рот меня чих-пых!