JWT — что это, структура, как декодировать
Что такое JWT
JSON Web Token (JWT) — это открытый стандарт (RFC 7519) для создания токенов доступа. Токен представляет собой компактную строку из трёх частей, разделённых точками: заголовок, полезная нагрузка и подпись. JWT позволяет безопасно передавать данные между двумя сторонами в формате JSON — например, между сервером и клиентом, между микросервисами, или в составе OAuth 2.0.
Ключевое отличие JWT от обычных сессионных токенов — самодостаточность. Токен содержит всю необходимую информацию о пользователе или разрешениях прямо внутри себя. Серверу не нужно обращаться к базе данных, чтобы проверить, кто перед ним — достаточно проверить подпись.
Структура JWT
JWT-токен выглядит как строка из трёх Base64URL-закодированных блоков, разделённых точками:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U
Заголовок (Header)
Первая часть токена содержит метаинформацию о самом токене — как минимум два поля:
{
"alg": "HS256",
"typ": "JWT"
}
alg — алгоритм подписи (HS256, RS256, ES256 и другие). typ — тип токена, почти всегда "JWT". Заголовок кодируется в Base64URL.
Полезная нагрузка (Payload)
Вторая часть содержит утверждения (claims) — данные, которые мы хотим передать. Существует три типа утверждений:
- Registered claims — стандартные поля:
iss(issuer, кто выпустил),sub(subject, о ком),aud(audience, для кого),exp(expiration, срок истечения),iat(issued at, когда выпущен),nbf(not before, недействителен до). - Public claims — открытые, зарегистрированные в IANA:
name,email,roleи другие. - Private claims — любые кастомные поля, согласованные между сторонами.
{
"sub": "1234567890",
"name": "Иван Петров",
"role": "admin",
"iat": 1718123456,
"exp": 1718209856
}
Важный момент: payload не шифруется, а только кодируется. Любой, у кого есть токен, может раскодировать Base64URL и прочитать содержимое. Никогда не кладите в JWT пароли, номера карт и другие секретные данные.
Подпись (Signature)
Третья часть — криптографическая подпись, которая гарантирует, что токен не был изменён. Подпись создаётся так:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
Если злоумышленник изменит роль в payload с "user" на "admin", подпись перестанет совпадать, и сервер отклонит токен. Но это работает только при правильной проверке подписи на сервере.
Алгоритмы подписи
HS256 (HMAC с SHA-256) — симметричный алгоритм. Один и тот же секретный ключ используется и для создания, и для проверки подписи. Прост в реализации, подходит для монолитов и внутренних микросервисов. Минус: если ключ утёк, злоумышленник может создавать токены от имени любого пользователя.
RS256 (RSA с SHA-256) — асимметричный алгоритм. Приватный ключ создаёт подпись, публичный — проверяет. Чаще всего используется в OAuth 2.0 и OpenID Connect. Плюс: даже если публичный ключ известен всем, подделать токен без приватного ключа невозможно. Минус: сложнее в настройке, ключи нужно ротировать.
ES256 (ECDSA с SHA-256) — современный асимметричный алгоритм на эллиптических кривых. Ключи компактнее, операции быстрее, чем RSA. Рекомендуется для новых проектов.
None — алгоритм без подписи. Существует формально, но использовать его в production категорически нельзя. Многие библиотеки по умолчанию блокируют alg: "none".
Как декодировать JWT
Декодировать JWT можно несколькими способами.
В командной строке (Linux/Mac) — декодируем Base64URL через base64 и jq:
# Берём вторую часть токена (payload)
echo "eyJzdWIiOiIxMjM0NTY3ODkwIn0" | base64 -d | python3 -m json.tool
На сайте jwt.io — скопируйте токен в поле, и сайт покажет расшифрованные header и payload, а также проверит подпись, если ввести ключ.
В коде — практически каждый язык программирования имеет библиотеки для работы с JWT:
- JavaScript/Node.js:
jsonwebtoken—jwt.verify(token, secret) - Python:
PyJWT—jwt.decode(token, key, algorithms=["HS256"]) - Java:
jjwt—Jwts.parser().setSigningKey(key).parseClaimsJws(token) - Go:
golang-jwt/jwt—jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {...})
Важно: всегда проверяйте подпись, срок действия (exp) и issuer (iss). Не полагайтесь только на декодирование payload — любой может создать токен с любым содержимым.
Где используются JWT
Аутентификация — после входа пользователя сервер выдаёт JWT, клиент сохраняет его в localStorage или cookie, и при каждом запросе прикрепляет заголовок Authorization: Bearer <token>. Сервер проверяет подпись и извлекает user_id из payload.
Микросервисы — сервис А создаёт JWT с правами пользователя и передаёт его сервисам B и C. Каждый сервис проверяет подпись, не обращаясь к центральному серверу авторизации.
Одноразовые ссылки — письмо со ссылкой для сброса пароля содержит JWT с коротким сроком жизни. Сервер проверяет токен и идентифицирует пользователя без обращения к базе.
Mobile-backend — приложение получает JWT при логине и хранит его в защищённом хранилище (Keychain/KeyStore). Токен живёт дольше сессии браузера.
Безопасность
- Короткий срок жизни access-токенов (15-60 минут) + refresh-токены для обновления.
- Хранение на клиенте: для веба — httpOnly cookie (не localStorage, он доступен для XSS-атак), для мобильных — Keychain/KeyStore.
- Проверка
alg: никогда не доверяйте заголовкуalgбез проверки. Некоторые библиотеки позволяли подменить RS256 на HS256, используя публичный ключ как секрет. - Чёрные списки: если пользователь вышел, а токен ещё не истёк, сервер должен иметь возможность отозвать токен. Ведите список отозванных JWT или используйте короткий срок жизни.
- Не храните секреты в payload: пароли, ключи, платёжная информация — только на сервере.
- Используйте HTTPS: JWT передаётся в открытом виде — без TLS его можно перехватить и использовать.
Попробовать инструмент
Чтобы на практике разобраться со структурой JWT, попробуйте наш декодер JWT на txtly.ru, где можно вставить токен и посмотреть все три его части в удобном интерфейсе — без кода и командной строки.