🟣 Проблема инвалидации
Это ахиллесова пята stateless-токенов. Представьте кейс:
1. Утром Вася логинится. Сервер выдает JWT со сроком жизни 24 часа.
2. Днем начальник узнает, что Васю уволили за нецелевое использование корпоративного принтера. Надо срочно отрубить ему доступ.
3. Админ нажимает «Заблокировать пользователя».
4. Но JWT-то у Васи на руках. Сервер нигде не хранит «список активных токенов» - это же stateless. Сервер видит: подпись валидна,
exp не истек - проходи, Вася.Почему это важно
В требованиях это часто звучит как «возможность немедленной блокировки учетной записи». С сессиями на сервере это тривиально. С JWT - архитектурная проблема.
Решения есть, но все они ломают "чистый stateless»:
🔄 Вести черный список отозванных токенов на сервере (усложнение, снова появляется зависимость от хранилища).
🔄 Делать токены очень короткоживущими (5 минут) и использовать Refresh Token (но это уже OAuth-подход, о нем позже).
🔄 Менять секретный ключ подписи (но тогда разлогинятся ВСЕ пользователи разом).
✅Вывод:
JWT плохо подходит для систем, где требуется мгновенная и точечная инвалидация сессий.
🟣 Раздутый Payload
Классический диалог разработчика 🤦♂️ и аналитика 🙆♀️:
🤦♂️: Чтобы не гонять лишние запросы в БД за профилем, давайте запишем в токен всё: ФИО, email, аватарку, массив ролей из 50 элементов, последние 10 заказов, уровень в игре...
🙆♀️: Пользователь получит свой профиль быстрее, звучит хорошо!
На деле - плохо. Этот токен прикрепляется к каждому HTTP-запросу. Загрузка страницы со списком товаров - 30 запросов к API. Каждый тащит с собой раздутый токен размером 4 КБ. Это лишний трафик на мобильных устройствах, лишняя нагрузка на сеть.
✅Правило хорошего тона:
В токене есть только то, что нужно для авторизации (идентификации и проверки прав) в рамках одного запроса.
userId, role, tenantId - ок. Данные профиля - нет. 🟣 Хранение на клиенте
Это уже зона ответственности фронтенда, но аналитик должен понимать риски.
🤜 localStorage / sessionStorage: Удобно. Но любой XSS-скрипт (а в большом приложении с кучей сторонних библиотек это не редкость) может просто прочитать
localStorage.getItem('token') и отправить злоумышленнику. Всё.🤜 HttpOnly Cookie: Безопаснее. JavaScript не имеет доступа к такой куке. Но появляется уязвимость к CSRF, с которой тоже нужно работать. + cookie - это автоматическая отправка, что не всегда удобно для мобильных клиентов.
✅ Вывод:
Выбирая способ хранения, мы балансируем между удобством разработки и моделью угроз. Для банковского приложения - только HttpOnly Cookie с кучей флагов (Secure, SameSite). Для внутренней админки за VPN - может, и localStorage простителен (но это не точно).
🦑 Что еще важного
Когда вы видите в требованиях "используем JWT", задайте три вопроса:
🧲 Как мы будем отзывать токен, если пользователя нужно срочно заблокировать?
🧲 Что именно мы кладем в payload? Есть ли там чувствительные данные или то, что сделает токен неподъемным?
🧲 Где и как клиент хранит токен? Соответствует ли это критичности данных?
В следующем посте перейдем к API Key и разберем, почему его нельзя использовать для логина пользователей, даже если очень хочется упростить схему.