JWT (JSON Web Token) — это строка, в которой сервер записал данные о пользователе и подписал их. Состоит из трёх частей через точку: заголовок, данные (payload) и подпись. Первые две части — JSON в кодировке Base64url, их прочитает любой, а подпись не даёт изменить их незаметно. Формат описан в RFC 7519.
Из чего состоит JWT
Токен выглядит как длинная строка из букв, цифр, дефисов и подчёркиваний, в которой ровно две точки. Они делят её на три части:
- заголовок (header) — JSON с типом токена
typи алгоритмом подписиalg, например{"alg":"HS256","typ":"JWT"}; - данные (payload) — JSON с утверждениями (claims): кто пользователь, когда токен выпущен и когда истекает;
- подпись (signature) — результат подписи первых двух частей секретным ключом.
Каждая из первых двух частей кодируется в Base64url: это Base64, где вместо + и / стоят - и _, а знаки = в конце отброшены. Поэтому все токены, где заголовок начинается с {"alg", начинаются с eyJhbGci. Подпись — это двоичные данные, тоже записанные в Base64url.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ItCQ0L3QvdCwIiwiaWF0IjoxNzYyMDAwMDAwLCJleHAiOjE3NjIwMDM2MDB9.PmDjtytZgVisghmY7-WyncyX490QtocQf8C-33-HCS8Подпись считают от строки «заголовок.данные». Сервер, получив токен, пересчитывает подпись своим ключом и сравнивает с той, что пришла. Если токен изменили хотя бы на один символ, подписи не совпадут. Для подписи используют HMAC (алгоритмы HS256, HS384, HS512, общий секрет на обе стороны) или пару ключей: закрытым ключом подписывает выпускающая сторона, а проверить может любой, у кого есть открытый ключ (RS256, PS256, ES256, EdDSA). Структура подписанных токенов описана в RFC 7515, список алгоритмов — в RFC 7518.
Что лежит в payload
Данные токена — обычный JSON, а набор полей определяет тот, кто его выпускает. Но у нескольких имён есть общий смысл (RFC 7519, раздел 4.1):
iss(issuer) — кто выпустил токен;sub(subject) — о ком токен, обычно идентификатор пользователя;aud(audience) — для кого токен предназначен;exp(expiration time) — когда токен перестаёт действовать;nbf(not before) — с какого момента токен действует;iat(issued at) — когда токен выпущен;jti— уникальный номер токена.
Время в exp, nbf и iat — Unix-время в секундах, то есть число секунд с 1 января 1970 года по UTC. Например, exp равное 1762003600 — это 1 ноября 2025 года, 13:26:40 по UTC. Это число легко перепутать с миллисекундами, которые в JavaScript отдаёт Date.now(): в токене должны быть именно секунды.
{
"sub": "1234567890",
"name": "Анна",
"iat": 1762000000,
"exp": 1762003600
}JWT и Bearer: в чём разница
Эти слова часто путают, потому что встречаются вместе: Authorization: Bearer eyJhbGci…. На самом деле они про разное.
- JWT — формат самого токена: как он устроен и подписан.
- Bearer — способ передачи: схема авторизации в заголовке
Authorization(RFC 6750). Слово значит «предъявитель»: кто предъявил токен, тот и получает доступ.
Bearer-токеном может быть и JWT, и обычная случайная строка (непрозрачный токен), которую сервер ищет у себя в базе. А JWT можно передать не только через Bearer, например в cookie или в параметре запроса. Поэтому «JWT или Bearer» не вопрос выбора: самая частая связка — JWT, переданный в схеме Bearer.
Раз токен действует у любого, кто его предъявил, его нужно беречь, как пароль: передавать только по HTTPS, не писать в логи и не показывать в адресной строке. При копировании из логов вместе с токеном часто захватывают слово Bearer : в нашем декодере его убирать не нужно.
Данные в токене не секретны
Самое частое заблуждение: раз токен подписан, значит, зашифрован. Нет. Подпись защищает от подделки, но не от чтения. Base64url — это не шифр, и содержимое payload читается без всякого ключа за секунду. Поэтому в токен нельзя класть пароли, номера документов, телефон и всё, что не должен видеть тот, у кого окажется токен. В нём место идентификатору, ролям и срокам.
Зашифрованный токен тоже существует: это JWE (RFC 7516), у него пять частей вместо трёх. Содержимое такого токена без ключа не прочитать. Обычные «JWT» в API почти всегда подписаны, но не зашифрованы.
Размер токена тоже имеет значение: он уходит с каждым запросом, а в cookie помещается около 4 килобайт. Лишних данных в нём лучше не держать.
jwt expired: что делать
jwt expired — сообщение библиотеки jsonwebtoken для Node.js (TokenExpiredError: jwt expired). Оно значит, что срок exp прошёл. В других библиотеках текст другой, смысл тот же: в PyJWT это ExpiredSignatureError: Signature has expired, в Java-библиотеке jjwt — ExpiredJwtException: JWT expired at ….
- Вставьте токен в декодер: мы покажем, когда он истёк, например «Токен истёк 3 дня назад».
- Если токен просрочен по-настоящему, получите новый: войдите заново или обновите его по refresh-токену, если ваша система его выдаёт. Просрочка — не сбой, а нормальное поведение: токены специально делают недолгими.
- Если токен выпущен только что, но уже просрочен, проверьте время на серверах. Разница часов даёт ошибки и в обратную сторону: токен «из будущего» отклоняют обычно из-за
nbf, иногда из-заiat. Многие библиотеки позволяют задать допуск на расхождение часов (leeway). - Если «срок» оказался в 1970 году или в далёком будущем, проверьте единицы:
expв миллисекундах вместо секунд даёт дату, которая наступит через десятки тысяч лет.
Срок проверяет библиотека на сервере при разборе токена. Отключать эту проверку (параметры вроде ignoreExpiration) ради «починки» ошибки не стоит: так просроченные токены начнут приниматься.
alg none и другие ловушки подписи
В заголовке можно указать "alg":"none". Такой токен не подписан вообще, его третья часть пустая, а запись заканчивается точкой. Стандарт допускает такие «незащищённые» токены (RFC 7519, раздел 6), но принимать их для входа нельзя: сочинить такой токен может кто угодно.
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwicm9sZSI6ImFkbWluIn0.Когда-то в некоторых библиотеках атакующий мог заменить алгоритм в заголовке и получить принятый сервером токен. Правило для разработчика одно: алгоритм проверки нужно задавать на стороне сервера, а не брать из заголовка токена. Если же сервер ждёт именно RS256, токен с HS256 или none он должен отклонить. Декодер на parsetools предупредит об alg: none, об отсутствии exp и о сроке больше года.
Частые вопросы
Что такое JWT токен простыми словами
Это строка из трёх частей, в которой сервер записал данные о пользователе и подписал их. По подписи можно проверить, что данные не менялись. Читать содержимое можно без ключа.
Как расшифровать JWT токен
Первые две части — JSON в Base64url, поэтому их достаточно раскодировать. Ключ нужен только для проверки подписи. Вставьте токен в декодер на parsetools: он покажет заголовок, данные и сроки.
JWT и Bearer токен: в чём разница
JWT — формат токена, Bearer — способ его передачи в заголовке Authorization. Bearer-токеном может быть и JWT, и непрозрачная случайная строка.
Что значит jwt expired
У токена прошёл срок действия, поле exp. Получите новый токен, войдите заново или обновите его по refresh-токену.
Можно ли хранить в JWT пароль
Нет. Данные токена не зашифрованы, их читает любой, у кого есть токен. Храните только идентификатор, роли и сроки.
Безопасно ли вставлять токен в онлайн-декодер
Только если он разбирается в вашем браузере. На parsetools токен не отправляется на сервер и остаётся только во вкладке браузера, пока вы её не закроете; секрет и ключ не сохраняются нигде. В сервисы, которые отправляют токен на свой сервер, живые токены лучше не вставлять: проверить, что с ним происходит дальше, нельзя.
Инструменты по теме
- JWT Расшифрует токен, покажет срок действия и проверит подпись
- Unix-время Переведёт timestamp в дату и дату в timestamp
- Base64 Переведёт текст и файлы в Base64 и обратно, покажет картинку
Ещё в справке
- Что такое JSON: формат, синтаксис и примеры Формат простыми словами: типы значений, правила, примеры и где он встречается. (откроется в новой вкладке)
- Ошибки в JSON и как их исправить Висячая запятая, кавычки, комментарии, BOM и ещё десяток причин, почему JSON не разбирается. (откроется в новой вкладке)