Как декодировать JWT и не перепутать payload с проверкой подписи
Разбираем header и payload JWT локально, читаем claims и отделяем диагностику токена от серверной проверки подписи, issuer, audience и срока действия.
Декодирование показывает, что записано в токене. Проверка подписи подтверждает,
что подписанные части соответствуют выбранному ключу и не менялись после
создания подписи. Затем сервер отдельно проверяет издателя, аудиторию, срок
действия и права. Для диагностики 401 или 403 полезно прочитать payload,
но одного декодирования для решения о доступе недостаточно.
| Операция | Нужен ключ | Что доказывает |
|---|---|---|
| Decode | Нет | Header и payload имеют читаемый формат |
| Verify signature | Секрет для HMAC или публичный ключ для асимметричной подписи | Подписанные части не менялись после создания подписи, и подпись соответствует выбранному ключу |
| Validate claims | Конфигурация сервиса | iss, aud, exp, nbf и другие claims подходят этому API |
Откройте JWT decoder, вставьте тестовый токен и нажмите «Декодировать». devdeck ожидает три части через точку, читает header и payload как UTF-8 JSON-объекты и выводит их с отступами. Подпись при этом не проверяется.
Что находится в трёх частях JWT
Обычный подписанный JWT выглядит так:
header.payload.signature
header часто содержит alg, typ и kid. payload содержит claims:
например, iss (кто выпустил), sub (субъект), aud (для кого), exp
(время окончания), nbf (не раньше какого времени) и прикладные поля.
signature связывает первые две части с ключом подписавшей стороны.
Header и payload используют Base64URL, а не шифрование. Их может прочитать любой получатель токена. Поэтому пароль, API key и другая тайна не должны попадать в payload. Отдельный разбор Base64URL и обычного Base64 есть в статье как декодировать Base64 локально.
Не доверяйте alg, роли или sub только потому, что они красиво показаны в
JSON. До проверки подписи злоумышленник может изменить эти значения и собрать
новую строку. Сервер должен сам ограничивать допустимые алгоритмы и выбирать
ключ по доверенной конфигурации.
Как читать payload при диагностике
Для ошибки авторизации проверьте claims в таком порядке:
iss: указан ли ожидаемый издатель.aud: указана ли ожидаемая аудитория API.exp: не закончился ли срок действия; NumericDate обычно задан в секундах Unix time.nbf: не используется ли токен раньше разрешённого времени.sub,scope,roles: совпадает ли ожидаемый пользователь и набор прав.kidв header: может ли проверяющий сервер найти нужный ключ.
JWT decoder показывает сырые значения и не вычисляет итоговый статус
валидности. Даже правдоподобный exp можно подделать вместе с payload. После
визуальной диагностики воспроизведите запрос через серверный компонент
проверки или доверенный сервис аутентификации.
Если payload неудобно сравнивать с ожидаемой структурой, скопируйте выведенный JSON в JSON formatter. Formatter проверит синтаксис и сделает вложенность читаемой, но тоже не знает контракт токена и не проверяет подпись.
Почему токен не декодируется
| Ошибка | Что проверить |
|---|---|
| Не три части через точку | Возможно, скопирован Bearer , пробел, обрезанный токен или другой формат |
| Некорректный Base64URL | В сегмент попал лишний символ либо потеряна часть строки |
| Header или payload не JSON | Это не обычный JWT либо сегмент повреждён |
| Пять частей вместо трёх | Вероятно, это compact JWE; ему нужен отдельный процесс расшифрования |
Декодируется, но API отвечает 401 | Проверяйте подпись, ключ, алгоритм, issuer, audience и время |
API отвечает 403 | Токен может быть валиден, но не иметь нужного scope или роли |
devdeck не удаляет префикс Bearer автоматически, поэтому вставляйте саму
строку от первой части header до подписи. Для alg: none инструмент допускает
пустую третью часть как корректную форму незащищённого JWT, но это не делает
такой токен доверенным.
Безопасный рабочий сценарий
Локальная обработка исключает отправку токена на сервер devdeck, но bearer token всё равно остаётся секретом доступа. По возможности используйте тестовый или уже отозванный токен, не отправляйте скриншоты с полной строкой и очистите поле после диагностики. Расширения браузера, история буфера обмена и запись экрана не становятся безопасными только из-за отсутствия серверной обработки.
Перед исправлением auth-кода сохраните короткий результат:
- какие
issиaudожидал проверяющий сервер; - какое серверное время сравнивалось с
expиnbf; - какой алгоритм разрешён конфигурацией;
- какой
kidи набор ключей использовались; - на каком шаге токен только декодировали, а на каком проверили подпись и claims.
Такая запись отделяет удобный просмотр JSON от решения о доверии и быстрее
находит настоящую причину 401.
Вопросы
Можно ли декодировать JWT без секрета или публичного ключа?
Да. Header и payload обычного трёхчастного JWT закодированы в Base64URL и читаются без ключа. Ключ нужен не для чтения, а для криптографической проверки подписи.
Проверяет ли JWT decoder в devdeck подпись?
Нет. Инструмент показывает header и payload, но не подтверждает подлинность токена. Нельзя принимать решения о доступе по одному декодированному результату.
Является ли Base64URL шифрованием?
Нет. Это способ представить байты безопасными для URL символами. Claims внутри JWT обычно видны любому, у кого есть токен.
Отправляется ли JWT на сервер devdeck?
Нет. Декодирование выполняется в браузере, а содержимое токена и разобранные header/payload не передаются в аналитику.