Безопасность · 3 мин чтения ·
Что внутри JWT и почему декодировать — не значит проверить
JSON Web Token выглядит как набор случайных символов, но прочитать его может любой. Что хранится в трёх его частях и какая ошибка приводит к дырам в безопасности.

JWT (JSON Web Token) — та длинная строка, благодаря которой вы остаётесь авторизованы во многих веб-приложениях и API. Она выглядит зашифрованной, но чаще всего это не так: любой, у кого есть токен, может прочитать его содержимое.
Три части через точку
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI0MiJ9.3q2-7w…
└ header ──────────┘ └ payload ───────┘ └ signature
Header сообщает, как подписан токен, например HS256 или RS256. Payload содержит claims: кто пользователь (sub), когда выдан токен (iat) и когда он истекает (exp), а также всё, что добавляет приложение, например роли. Обе части — это обычный JSON в кодировке base64url, а это кодирование, а не шифрование.
Главное — подпись
Третья часть — подпись первых двух, сделанная с помощью секрета или закрытого ключа. Проверить её может только сервер с нужным ключом. Если кто-то изменит в payload хотя бы один символ, скажем роль с user на admin, подпись перестанет совпадать.
Декодировать — не значит проверить
Токен, который нормально декодируется, говорит о том, что он утверждает, а не о том, правда ли это. Ваш бэкенд должен проверять подпись ключом, отклонять токены с истёкшим exp и принимать только ожидаемые алгоритмы, никогда не «none». Библиотеки JWT делают это за вас; пропустить проверку — классическая уязвимость.
Практические правила
Не кладите в payload секреты вроде паролей: его можно прочитать. Делайте срок жизни токенов коротким. Относитесь к токену как к паролю, пока он действителен: любой, кто его скопирует, сможет им пользоваться до истечения срока.
Где хранить токен в браузере
Всё, что лежит в localStorage, может прочитать любой скрипт на странице, поэтому одна уязвимость межсайтового скриптинга (XSS) способна раскрыть токен. Cookie с флагом HttpOnly вообще недоступна для JavaScript, и этот риск исчезает; дополните её флагами Secure и SameSite и защитой от подделки межсайтовых запросов (CSRF). Идеального варианта нет, но для сессионных токенов cookie HttpOnly — более безопасный выбор по умолчанию.
Срок действия и токены обновления
JWT нельзя «разлогинить» сам по себе: он действует до момента exp, если только сервер не ведёт список отозванных токенов. Поэтому токены доступа обычно живут минуты, а не дни. Более долгоживущий токен обновления, который хранят аккуратнее и проверяют на сервере, позволяет получить новый токен доступа, когда старый истёк.
Основные поля одним взглядом
iss издатель кто создал токен
sub субъект пользователь или клиент, к которому он относится
aud аудитория какой сервис должен его принимать
exp истекает время Unix, после которого он недействителен
nbf не раньше время Unix, до которого он недействителен
iat выдан время Unix его создания
Поля времени — это метки времени Unix в секундах. Сервер должен проверять не только exp, но и aud: валидный токен, выданный для одного сервиса, не должен приниматься другим.
Как прочитать токен
Декодер JWT от 4Dev разбивает токен на части и показывает header и payload в виде читаемого JSON. Он только декодирует и не проверяет подпись. Токен отправляется на сервер 4Dev для декодирования и не логируется и не сохраняется, но всё же не вставляйте действующие токены из продакшена и отзывайте любой токен, который мог утечь.