Что такое JWT — и почему сервер тебя не помнит, но всё равно пускает

Странная штука: ты вошёл в приложение один раз, а оно «помнит» тебя на каждой следующей странице. Логично подумать, что сервер где-то записал «этот человек залогинен». Но чаще всего — нет. Сервер про тебя ничего не хранит. Он каждый раз заново проверяет пропуск, который ты сам ему показываешь.
Этот пропуск и есть JWT (JSON Web Token). И в нём спрятана одна неочевидная деталь, на которой новички обжигаются: всё, что внутри токена, может прочитать кто угодно. Разберёмся, как это работает и почему это всё равно безопасно.
Что такое JWT простыми словами
Представь фестиваль. На входе тебе надевают браслет. Дальше ты ходишь где хочешь, и охрана на каждой зоне просто смотрит на браслет — она не звонит в кассу проверять, покупал ли ты билет. Браслет сам по себе и есть доказательство.
JWT — это такой же браслет, только цифровой. Когда ты входишь, сервер выдаёт тебе токен. Браузер хранит его и прикладывает к каждому запросу. Сервер смотрит на токен, убеждается, что он настоящий, — и пускает. Ему не нужно лезть в базу и искать «а кто это». Ответ уже в самом токене.
Это называется stateless — «без состояния». Сервер не держит у себя журнал сессий. Вся нужная информация едет с тобой.
Три части одного токена
JWT выглядит как длинная строка с двумя точками: xxxxx.yyyyy.zzzzz. Это три склеенные части.
- Header — служебная шапка: какой алгоритм подписи используется.
- Payload — полезная начинка: кто ты (id пользователя), какие у тебя права, до какого времени токен годен. Это и есть «что написано на браслете».
- Signature — подпись. Сервер берёт первые две части и свой секретный ключ, прогоняет через алгоритм и получает подпись. Это печать, которую нельзя подделать, не зная секрета.
Когда токен приходит обратно, сервер пересчитывает подпись своим секретом и сравнивает. Совпало — токен настоящий, его никто не трогал. Не совпало — в мусор. Секретный ключ при этом живёт не в коде, а в переменных окружения сервера — его нельзя показывать никому.
Главная ловушка: внутри ничего не зашифровано
А теперь — та самая деталь, которая ломает интуицию.
Payload не зашифрован. Он просто закодирован в base64 — это не шифрование, а способ записи, который разворачивается обратно одной строчкой. Любой, у кого есть твой токен, может прочитать всё, что внутри: твой id, почту, роль. Можешь сам проверить — вставь токен на сайте jwt.io и увидишь содержимое открытым текстом.
Отсюда железное правило: никогда не клади в JWT секреты — пароли, номера карт, приватные данные. Туда кладут только то, что не страшно показать.
«Но если payload открыт, почему его нельзя подделать?» — Можно прочитать, но нельзя переписать. Если изменить хоть один символ внутри, подпись перестанет сходиться, потому что секрета у тебя нет. Подпись защищает не от чтения, а от подмены.
Зачем это тебе как создателю приложения
Главный плюс stateless-токенов — масштабируемость.
Представь, что у тебя не один сервер, а пять — за балансировщиком, который кидает запросы то на один, то на другой. Если бы сервер хранил сессии у себя в памяти, при переходе на соседний сервер ты бы «вылетал» — он тебя не знает. С JWT этой проблемы нет: токен едет с тобой, и любой сервер проверит его своим секретом. Не нужна общая база сессий, не нужна лишняя связность.
Минус честно тоже есть: раз сервер ничего не хранит, отозвать один конкретный токен до истечения срока сложно — он валиден, пока не протухнет. Поэтому JWT делают короткоживущими (минуты-часы) и обновляют отдельным refresh-токеном.
На практике ты редко собираешь это руками. Готовые сервисы вроде Supabase, Clerk или Auth0 выдают и проверяют JWT за тебя — часто в связке с OAuth-входом «через Google». Но теперь, когда что-то сломается, ты понимаешь, что именно происходит под капотом.
Частые вопросы
JWT — это то же самое, что cookie?
Не совсем. Cookie — это место хранения в браузере; JWT — это формат самого токена. JWT часто кладут именно в cookie (это удобно и безопасно), но можно хранить и иначе. То есть это не «или-или»: токен в формате JWT вполне живёт внутри cookie.
Где правильно хранить JWT на клиенте?
Самый безопасный вариант — в cookie с флагом httpOnly: тогда до токена не дотянется чужой JavaScript на странице. Хранить в localStorage проще, но рискованнее: при атаке через внедрённый скрипт токен можно украсть. Для начала доверься тому, как это делает твой сервис аутентификации по умолчанию.
Зачем нужен refresh-токен, если уже есть JWT?
Чтобы совместить безопасность и удобство. Основной токен делают короткоживущим — украдут, протухнет быстро. А чтобы тебя не выкидывало каждые 15 минут, рядом живёт долгий refresh-токен: он молча выписывает новый основной токен, пока ты активен.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





