Security basics, часть 4: JWT



Статей про JWT много, но все они делают упор на авторизацию. Но JWT используется по-разному, поэтому начну с общей схемы, а потом перейду на auth.



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



Вопрос — где хранить корзину с товарами?



🔸 На сервере



Когда клиент начинает работу с приложением, на сервере создаётся запись типа



sessionID - { /*info*/ }



Там хранится информация для текущего сеанса.



Когда пользователь вводит логин-пароль, то получает обратно sessionID. SessionID сохраняется в cookies и автоматически добавляется в каждый запрос.



Так сервер понимает, какой пользователь прислал запрос, и с какой информацией работать.



🔸 На клиенте



Если на сервере не хранится ничего временного, то в каждом запросе клиент отправляет все нужные данные.



Браузер отправил логин-пароль — получил обратно имя пользователя и количество накопленных баллов. Сохранил у себя.



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



И тут вопрос — что мешает клиенту передать ложную информацию? Например, что у него 9999999 бонусных баллов.



Тут мы подходим к JWT, он гарантирует корректность присланных ранее данных. Как это работает:



1️⃣ Сервер шлёт какую-то информацию и подписывает её:



"bonus":10

"bonus sign":"Dfhdy76"



Подпись, напомню, вычисляется из хэша данных и приватного ключа сервера.



2️⃣ Клиент хранит данные у себя и обратно отправляет вместе с той же подписью:



"city":"moscow"

"bonus":10

"bonus sign":"Dfhdy76"



3️⃣ Сервер проверяет корректность своим публичным ключом. Если клиент пришлёт "bonus" : 99999, то сервер сразу распознает обман.



JWT токен состоит из 3х частей:



▪️ Заголовок с алгоритмом подписи:

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



▪️ Что-то полезное:

{"bonus":10, "status":"vip"}



▪️ Подпись



По сути это два JSON и строка. Чтобы передавать это как цельный объект, каждая часть кодируется Base64. Части соединяются между собой через точку в одну строку:



eyJh.TYDkwI.SflKxwRJSM



И хотя механизм универсальный, чаще всего он используется для авторизации и помогает серверу понять, кто выполняет запрос:



🔹 Пользователь вводит логин пароль

🔹 Сервер отвечает JWT токеном, внутри которого что-то вроде



"userId":34563847638



🔹 Токен каждый раз передаётся в хэдере HTTP запроса

🔹 Сервер валидирует подпись



Важные дополнения:



JWT ничего не шифрует, только заверяет подлинность данных. Поэтому в JWT токенах не следует передавать пароли или что-то секретное.



Важно, чтобы JWT токены хранились и передавались безопасно. Ведь если токен с авторизацией перехватит злоумышленник, то он сможет выдать себя за пользователя.



Что делать: использовать HTTPS и самые новые версии браузеров с безопасным хранением cookies.



В принципе это всё, что нужно для базового понимания JWT. Больше деталей:

▫️ JWT Security Best Practices

▫️ Спецификация JWT