Перейти к содержимому
🚀 Уже доступно 10 инструментов, бесплатно навсегда — и список растёт
Главная›Блог›JWT простыми словами: разбор и отладка JSON Web Token
Руководства

JWT простыми словами: разбор и отладка JSON Web Token

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

✍ Автор — основатель и CEO, команда BuildToolForge🗓 2026-10-17⏱ 12 мин
jwtjson web tokenauthenticationclaimsapi security
Руководство по инструменту безопасности2026

JWT
Без загадок

Что лежит внутри JSON Web Token

Заголовок · Полезная нагрузка · Подпись

jwt · decode
$ decode eyJhbGciOiJIUzI1NiJ9...
header{"alg":"HS256"}
payload{"sub":"1234"}
exp1799884800
✓ декодировано в браузере · подпись не проверяется
Стандартные claims
iss
Издатель
sub
Субъект
aud
Аудитория
exp
Истечение
nbf
Не ранее
iat
Выпущен
Декодирование в браузереЧитайте каждый claimЗамечайте истечениеДекодирование — не проверка

Что такое JWT на самом деле

JSON Web Token — это строка. В этом весь фокус. Вместо того чтобы выдать клиенту идентификатор сессии и держать саму сессию на сервере, вы выдаёте ему подписанное утверждение — «это пользователь 4821, вот его права, всё это истекает в 14:05» — и позволяете его носить с собой. Любой сервис, доверяющий ключу подписи, прочитает это утверждение и примет решение, не обращаясь к базе данных.

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

Токен выглядит как три блока непонятных символов, разделённые точками:

eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleS0yIn0.eyJzdWIiOiI0ODIxIiwiZXhwIjoxNzY1MTExMTExfQ.3xS7_c9Nn-aQ

Он не зашифрован. Первые два блока — это обычный JSON в Base64url, безопасном для URL алфавите, где + и / заменены на - и _, а завершающие = отброшены. Любой превратит их обратно в JSON за секунду — именно это и делает декодер JWT.

Три части и назначение каждой

Разбейте токен по точкам — получите заголовок, нагрузку и подпись.

Заголовок

Маленький и почти всегда про ключи. alg называет алгоритм подписи, typ обычно равен JWT, а kid — идентификатор ключа, который говорит проверяющей стороне, какой открытый ключ забрать, если у издателя их несколько. Если токен внезапно перестал проходить проверку после ротации ключей, смотрите сначала на kid.

Полезная нагрузка

Клеймы — собственно само утверждение. Часть из них зарегистрирована спецификацией (iss, sub, aud, exp, nbf, iat, jti), остальное — то, что решил добавить ваш издатель: scope, roles, tenant_id, адрес почты, флаг функции.

Подпись

MAC или цифровая подпись по первым двум частям — ровно в том виде, в каком они стоят в строке. Эта деталь важна: подпись покрывает закодированные байты, поэтому если пересобрать JSON и закодировать заново, получится токен, который больше не проходит проверку, даже если данные те же. Никогда не пересобирайте токен, чтобы «привести его в порядок».

Как декодировать токен и на что смотреть первым делом

Вставьте строку целиком в декодер, вместе с точками. Если вы скопировали её из запроса, уберите префикс Bearer — или возьмите инструмент, который уберёт его сам. Дальше читайте в таком порядке:

  1. Вообще декодировалось? Если декодер говорит, что части — не корректный JSON в Base64url, токен пришёл обрезанным или испорченным. Так выглядят и кука, упёршаяся в лимит размера, и заголовок, разорванный переносом строки.
  2. exp. Истечение срока объясняет большинство жалоб «пять минут назад работало», и исключать надо в первую очередь именно его.
  3. aud и iss. Токен, выпущенный для другого получателя, — совершенно корректный токен, который ваш API правильно отклоняет.
  4. Собственные клеймы. Спорить о том, то ли лежит в scope, стоит только после того, как стандартные клеймы сошлись.

Декодируйте локально, где можете. Токен — это действующий доступ, поэтому вставить его на случайный сайт — ошибка того же класса, что вставить туда пароль: любой нормальный инструмент декодирует в браузере и никуда ничего не отправляет.

Клеймы, от которых зависит, сработает ли токен

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

  • exp — срок действия, метка Unix в секундах. Значение в миллисекундах здесь — классическая ошибка: оно попадает в 57000 год, и токен не истекает никогда. Хороший декодер показывает и настоящую дату, и сколько времени прошло.
  • nbf — not before. До этого момента токен недействителен. Намеренно используется редко, иногда выставляется случайно на машине с убежавшими вперёд часами.
  • iat — время выпуска. Полезно, чтобы отклонять формально не истёкшие, но подозрительно старые токены, и чтобы заметить проблему с часами, когда iat в будущем.
  • aud — получатель, для кого токен предназначен. API, который пропускает эту проверку, с радостью примет токен, выпущенный вашим же другим сервисом для себя, а это реальный путь повышения привилегий между микросервисами.
  • iss — издатель. Жёстко закрепите ожидаемого издателя и берите ключи только из опубликованного им набора.

jti стоит особняком: это уникальный идентификатор токена. Он что-то значит только если вы его храните и сверяете, но именно он делает возможным отзыв одного конкретного токена.

Декодировать — не значит проверить

Вот место, где спотыкаются чаще всего. Декодирование читает Base64url и показывает JSON. Оно говорит, что токен утверждает. И ничего не говорит о том, правда ли это.

Любой может написать {"sub":"1","role":"admin"}, закодировать в Base64url, приписать в конец произвольную строку вместо подписи и отдать вам. В любом декодере, включая наш, это раскодируется идеально. Работать этому не даёт шаг проверки: пересчитать подпись ключом издателя и отвергнуть токен, если она не совпала. Для этого шага нужен секрет или открытый ключ, его место — на вашем сервере, и ни один браузерный инструмент не сделает его за вас.

Поэтому относитесь к декодеру как к показаниям прибора, а не как к доказательству. «Я декодировал, там написано admin» — это не находка по безопасности. «Мой сервер проверил подпись, и там написано admin» — да.

Почему с виду правильный токен получает 401

Если токен декодируется чисто, а API всё равно его не принимает, почти всегда дело в одном из этого списка:

  • Истёк. Сверяйте exp с часами сервера, а не своими.
  • Расхождение часов. Сервер, убежавший на пару минут вперёд, отвергнет только что выпущенные токены. Большинство библиотек допускают небольшой запас именно поэтому; если у вас он нулевой, это стоит пересмотреть.
  • Не тот получатель. Частое дело, когда один провайдер идентификации обслуживает несколько API.
  • Ротация ключей. Издатель подписал новым ключом, у проверяющей стороны в кеше ещё старый набор, и kid больше не находится.
  • Токен вообще не дошёл. Отсутствующий или искажённый заголовок Authorization, потерянная кука или прокси, вырезающий заголовки. Посмотрите, что сервер реально получил, прежде чем винить токен: поиск HTTP-кодов состояния и наше руководство по кодам состояния помогают отличить 401 от 403, который означает совсем другое.

401 или 403?

401 значит, что доступа нет, он истёк или не проверяется: исправляйте токен. 403 значит, что доступ был в порядке, а ответ всё равно «нет»: исправляйте права или клейм scope. Сервисы, отдающие 401 при провале авторизации, отправляют людей отлаживать токен, который никогда и не был проблемой.

Как выбрать и проверить алгоритм подписи

На практике важны два семейства. HS256 — это HMAC с общим секретом: кто может проверить, тот может и подписать, что нормально внутри одного сервиса и плохо подходит между организациями. RS256 и ES256 подписывают закрытым ключом, а проверяют открытым, поэтому API может проверять токены, которые сам выпустить бы не смог.

И есть alg: none — неподписанный токен, который спецификация разрешает и который принимать нельзя никогда. Он есть в стандарте, значит был в библиотеках, значит его эксплуатировали: проверяющей стороне, берущей алгоритм из заголовка самого токена, можно заявить «этот не подписан, просто поверь». Родственный приём подсовывает проверяющему на RS256 токен HS256, подписанный открытым ключом в роли секрета HMAC.

Защита — одна строчка политики: решите, какие алгоритмы вы принимаете, до того как взглянуть на токен, и отвергайте всё остальное. Заголовок — это подсказка о том, какой ключ взять, а не указание, проверять ли подпись. Если ваш декодер помечает alg: none красным, причина в этом.

Чего в нагрузке быть не должно

Поскольку нагрузка закодирована, а не зашифрована, каждый клейм открыт любому, у кого есть токен, — а токены оказываются в хранилище браузера, в логах, в системах сбора ошибок, в тикетах поддержки и на скриншотах. Не кладите в нагрузку:

  • Ничего из того, что вы не поставили бы в URL: пароли, ключи API, номера карт, медицинские данные.
  • Внутренние идентификаторы, которые не хотелось бы публиковать: первичные ключи базы, внутренние имена хостов, условия лицензии.
  • Большие блоки данных. Токен едет с каждым запросом; килобайт клеймов — это килобайт на каждый вызов, а раздутые токены надёжно упираются в лимиты размера заголовков на прокси.

Держите токены и подальше от URL. Токен в строке запроса попадает в логи сервера, в заголовки Referer и в историю браузера. Передавайте его в заголовке Authorization и убедитесь, что сайт задаёт разумный Referrer-Policy: об этом рассказывает наше руководство по заголовкам безопасности, а проверка заголовков безопасности покажет, что вы отдаёте сегодня.

Срок действия, обновление и проблема отзыва

JWT нельзя вернуть обратно. Выпущенный токен действует до exp, что бы ни случилось с аккаунтом за ним. Отключите пользователя — его токен доступа будет работать, пока не кончится срок. Это цена отказа от обращения к базе на каждом запросе.

Стандартный ответ — два токена. Короткоживущий токен доступа (минуты, не дни) несёт клеймы и делает работу. Долгоживущий токен обновления хранится на сервере, сверяется с базой при каждом использовании и отзывается мгновенно. Выход из системы тогда означает аннулировать токен обновления и подождать короткое окно, пока токен доступа умрёт сам.

Выбирайте окно осознанно: это разрыв между отзывом доступа и фактическим прекращением доступа. Пятнадцать минут — распространённый компромисс. Часы оправдать трудно; дни означают, что отзыва у вас нет вовсе. А если нужен мгновенный отзыв, ведите список запрещённых значений jti — и вот вы снова обращаетесь к хранилищу на каждом запросе, и обычная сессия может оказаться проще по устройству.

Что бы вы ни выбрали, цикл отладки один и тот же: декодировать токен, прочитать exp и aud, сверить часы, затем проверить подпись на сервере. Четыре шага в этом порядке — и почти любая проблема с токеном раскрывается на первых двух.

Связанные инструменты и руководства:

Частые вопросы

Можно ли декодировать JWT без секретного ключа?⌄

Да. Заголовок и нагрузка закодированы в Base64url, а не зашифрованы, поэтому их прочитает любой, у кого есть токен. Ключ нужен только для проверки подписи. Именно поэтому в нагрузку нельзя класть чувствительные данные.

Безопасно ли вставлять JWT в онлайн-декодер?⌄

Только если декодирование происходит в вашем браузере. До истечения срока токен — действующий доступ, так что инструмент, отправляющий его на сервер, работает с вашими учётными данными. Наш декодер работает целиком в странице и никуда токен не отправляет, но самая безопасная привычка — по возможности брать истёкшие или тестовые токены.

Почему токен декодируется нормально, но всё равно возвращается 401?⌄

Декодирование доказывает лишь, что строка правильно устроена. Обычные причины: уже прошедший exp, расхождение часов между издателем и проверяющей стороной, aud с другим API или kid, который проверяющая сторона не может разрешить после ротации ключей.

Чем JWT отличается от сессионной куки?⌄

Сессионная кука — это указатель: сервер держит состояние и смотрит его на каждом запросе, поэтому отзыв мгновенный. JWT несёт состояние сам, поэтому обращаться никуда не нужно — и ничего нельзя забрать до истечения срока. JWT лучше масштабируется между сервисами; сессии дают контроль.

Что выбрать, HS256 или RS256?⌄

HS256 использует один общий секрет, поэтому кто может проверить, тот может и подписать. Внутри одного сервиса это допустимо. RS256 и ES256 подписывают закрытым ключом и проверяют открытым — именно это нужно, как только участников больше одного. В любом случае закрепите список принимаемых алгоритмов на стороне проверки и никогда не доверяйте значению alg из токена.

Об авторе
Основатель и CEO, BuildToolForge
Мы в X: @Buildtoolforge

Более 15 лет практического опыта в веб-разработке и безопасности. Специализация — практическая веб-безопасность: чтобы сайты были защищёнными, надёжными и легко диагностировались. BuildToolForge создан, чтобы такие проверки были бесплатными, приватными и понятными. Инструменты по возможности работают прямо в браузере, а всё, что вы вводите в инструмент, не сохраняется.

Как мы пишем руководства: Каждое руководство основано на практическом опыте, сверено с официальными стандартами и проверено нашими инструментами на реальных доменах. Мы обновляем руководства, когда меняются стандарты или инструменты. Нашли ошибку? Напишите нам: contact@buildtoolforge.com.

Последнее обновление: 2 ноября 2026 г.