Декодер JWT
Вставьте JSON Web Token и прочитайте, что в нём сказано: кто его выдал, для кого он, что он разрешает и когда перестаёт работать. Токен не покидает эту страницу.
Токен декодируется прямо на этой странице, пока вы вводите или вставляете его: он не отправляется нам, не сохраняется и не попадает в адрес. Начальное Bearer и переносы строк игнорируются.
Обращайтесь с настоящим рабочим токеном как с паролем: пока он не истёк, любой, у кого он есть, может действовать от вашего имени, поэтому не вставляйте его на сайты, которые вы не контролируете.
Три куска текста, соединённые точками
Когда вы вошли на сайт, сервер должен узнавать вас снова при следующем запросе. Распространённый способ это сделать: выдать браузеру короткую подписанную записку вида «это пользователь 48213, ему можно читать заказы, до 15:15». Эта записка и есть JSON Web Token, или JWT.
JWT выглядит как одна длинная случайная строка, но у него всегда одна и та же форма, header.payload.signature.
- Заголовок (header) представляет собой небольшой JSON-объект, который называет алгоритм подписи (
alg) и часто использованный ключ (kid). - Полезная нагрузка (payload) представляет собой JSON-объект из claims, то есть утверждений, таких как
sub(кто),aud(для какого сервиса) иexp(до какого момента). - Подпись (signature) представляет собой печать, вычисленную из первых двух частей и ключа.
Заголовок и payload записаны в Base64URL, способом записать байты буквами, цифрами, - и _, чтобы они пережили путь через адрес или HTTP-заголовок. Поэтому же почти каждый токен начинается с eyJ: так в этой кодировке выглядит {".
Закодировано не значит зашифровано
Base64URL всего лишь способ записи. Он ничего не запирает, и чтобы превратить его обратно в текст, ключ не нужен, а больше эта страница ничего и не делает. Значит, подписанный JWT не скрывает вообще ничего. Если в payload лежит адрес почты, роль или внутренний ID, прочитать его может любой, к кому попал токен, будь то расширение браузера, журнал прокси или скриншот.
Подпись даёт целостность. Измените один символ payload, и печать перестанет совпадать, поэтому сервер отклонит токен. Прочитать его по-прежнему можно. Переписать нельзя.
Токен из пяти частей представляет собой другой объект, JWE, и его содержимое действительно зашифровано. Этот инструмент показывает его заголовок, объясняет пять частей и на этом останавливается. Он никогда не просит ключ.
Что читает эта страница и о чём предупреждает
Декодер убирает начальный Bearer, пробелы и переводы строк, делит токен на части и выводит заголовок и payload в виде отформатированного JSON. Затем он перебирает claims по одному. Три даты, exp, nbf (не раньше) и iat (выдан), представляют собой число секунд с 1 января 1970 года. Вы видите их в своём часовом поясе и в UTC, с живым отсчётом вроде «действителен ещё 12 минут».
| Находка | Почему это важно |
|---|---|
| Истёк или ещё не действует | Сравнение идёт с часами вашего устройства. Правильно настроенный сервер отклонит токен. |
Нет claim exp | Токен работает вечно, если только сервер не ведёт список отозванных токенов. |
| Срок жизни больше 30 дней | Украденный токен остаётся полезным всё это время. |
alg равен none | Токен не подписан. Написать такой может кто угодно. |
| Даты в миллисекундах | Значение в 1000 раз больше нужного означает, что для строгого получателя токен никогда не истекает. |
| Персональные данные или поле с названием, как у секрета | Их может прочитать каждый, у кого есть токен. |
jku, x5u или jwk в заголовке | Токен указывает на собственный ключ, а так может сделать и подделыватель. |
Есть и пара слов об алгоритме. HS256 использует один общий секрет и для подписи, и для проверки. RS256, ES256 и EdDSA используют пару ключей: закрытый ключ подписывает, открытый проверяет, поэтому сервисы, которые только проверяют токены, не могут их создавать.
Чего декодирование не скажет
Эта страница не проверяет подпись. Для этого нужен секрет или открытый ключ выдавшей стороны, а страницу, которая просит ваш секрет для подписи, лучше сразу закрыть. Поэтому поддельный и настоящий токены выглядят здесь одинаково. Читайте результат как «вот что утверждает токен», но никогда как «этот токен действителен».
По той же причине «не истёк» означает лишь, что exp позже часов вашего устройства. Сервер мог отозвать токен час назад.
Если вы пишете принимающую сторону, важные проверки происходят в вашем коде. Принимайте только ожидаемые алгоритмы, проверяйте подпись ключом, которому уже доверяете, затем сравнивайте iss, aud и exp с тем, что ожидаете. Используйте поддерживаемую библиотеку и никогда не ветвите логику по alg, который просит токен.
Действующий токен равен учётным данным
Пока он не истёк, bearer-токен работает для любого, кто его предъявит. Вставьте рабочий токен на сайт, и вы отдали его этому сайту, если только декодирование не происходит в вашем браузере. Здесь оно происходит в браузере. Ни один запрос не несёт токен, он не пишется в адресную строку и не сохраняется в хранилище браузера. Верить нам на слово не обязательно: следите за вкладкой «Сеть» в инструментах разработчика или загрузите страницу и отключитесь от сети, прежде чем вставлять.
И всё же самая надёжная привычка: отлаживать на токенах тестовой учётной записи или на истёкших. Если настоящий токен попал в чат, тикет или публичный журнал, выйдите из всех сеансов или попросите выдавшую сторону его отозвать.
Частые вопросы
Безопасно ли вставлять JWT в онлайн-декодер?
Только если декодер работает в вашем браузере и ничего не отправляет. Этот делит и декодирует токен локально, не делает с ним никаких запросов и ничего не сохраняет. Для рабочих токенов всё равно лучше брать истёкший или токен тестовой учётной записи.
Можно ли декодировать JWT без секретного ключа?
Да. Заголовок и payload представляют собой текст в Base64URL, который любой может превратить обратно в JSON. Секрет или ключ нужен только для проверки подписи или для создания токена, который примет сервер.
Что означают exp, iat и nbf в JWT?
exp означает момент, когда токен перестают принимать, iat момент выдачи, а nbf момент, с которого его начинают принимать. Все три представляют собой число секунд с 1 января 1970 года (UTC), а не миллисекунд.
Почему мой токен начинается с eyJ?
Заголовок представляет собой JSON-объект, поэтому он начинается с {", а эти символы в Base64 всегда превращаются в eyJ. Payload начинается так же по той же причине.
Чем отличаются HS256 и RS256?
HS256 подписывает и проверяет одним общим секретом, поэтому любой сервис, способный проверить токен, может и подделать его. RS256 подписывает закрытым ключом и проверяет открытым. Тогда множество сервисов могут проверять токены, а создавать их может только выдавшая сторона.
Чем опасен токен с alg none?
У него нет подписи, поэтому его содержимое может изменить кто угодно. Сервер, который его принимает, позволяет людям самим выбирать себе ID пользователя или роль. Получатели должны перечислить принимаемые алгоритмы и отклонять всё остальное.