JWT: что это, структура JSON Web Token и применение

Автор: IT Sectr Опубликовано: 2026-04-05 Время чтения: 9 мин

JWT (JSON Web Token) — это компактный формат передачи данных между сторонами в виде JSON-объекта, защищённого цифровой подписью. Токен может быть подписан с помощью HMAC (симметричный ключ) или RSA/ECDSA (асимметричная пара), что гарантирует целостность и подлинность данных. По данным IETF RFC 7519, 2015, JWT используется в миллионах приложений для аутентификации, безопасного обмена claims и как формат ID Token в OpenID Connect.

Главное

  • JWT — самодостаточный токен, содержащий все данные для проверки в себе
  • Структура — три части: header, payload и signature, разделённые точками
  • Подпись — гарантирует, что данные не были изменены после создания токена
  • Stateless — серверу не нужно хранить сессию, что упрощает масштабирование
  • Безопасность — JWT не шифрует данные, только подписывает; чувствительная информация не должна помещаться в payload

Что такое JWT?

JSON Web Token (JWT) — это открытый стандарт (RFC 7519), определяющий компактный и самодостаточный способ передачи информации между сторонами в виде JSON-объекта. Информация в JWT называется claims — утверждения о субъекте (пользователе) и дополнительных атрибутах. Каждый claim — это пара ключ-значение: идентификатор пользователя, роль, срок действия, издатель.

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

По данным Auth0, 2025, более 65% мобильных и веб-приложений используют JWT как основной формат токена для API-аутентификации, опережая случайные строки (opaque tokens) и сессионные идентификаторы.

Структура JWT: header, payload и signature

JWT состоит из трёх частей, разделённых точками: header.payload.signature. Каждая часть представляет собой Base64url-закодированный JSON. Рассмотрим каждую часть подробно.

Header — алгоритм и тип токена

Header содержит два обязательных поля: alg (algorithm — алгоритм подписи) и typ (type — тип токена, всегда "JWT"). Алгоритм может быть симметричным (HS256 — HMAC с SHA-256) или асимметричным (RS256 — RSA с SHA-256, ES256 — ECDSA с P-256). Асимметричные алгоритмы предпочтительнее, поскольку позволяют клиенту проверять подпись без владения секретным ключом.

Пример декодированного header:

json
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "key-id-1"
}

Payload — claims и данные

Payload содержит claims — утверждения о субъекте. Claims делятся на три типа: зарегистрированные (iss, sub, aud, exp, nbf, iat, jti), публичные (определяемые разработчиком в IANA Registry) и приватные (согласованные между сторонами). sub (subject) — уникальный идентификатор пользователя. exp (expiration) — timestamp истечения токена. iss (issuer) — издатель токена.

json
{
  "sub": "user-abc-123",
  "iss": "https://auth.example.com",
  "aud": "my-mobile-app",
  "exp": 1812345678,
  "iat": 1812342078,
  "role": "premium_user"
}

Signature — проверка целостности

Signature создаётся путём применения алгоритма подписи к конкатенации header и payload с использованием секретного или приватного ключа. Формула: HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) для HMAC, или RSASHA256(...) для асимметричного алгоритма. Получатель вычисляет подпись тем же способом и сравнивает с полученной — если они совпадают, данные не были изменены.

Как работает JWT: создание и верификация

Процесс работы с JWT состоит из двух фаз: создание (выпуск) токена сервером аутентификации и проверка токена клиентом или сервером ресурсов. Сервер аутентификации получает учётные данные пользователя, создаёт payload с claims и подписывает его. Полученный JWT отправляется клиенту в ответе на запрос логина или в теле ответа OAuth 2.0 / OpenID Connect.

JWT в мобильной аутентификации

В мобильных приложениях JWT используется следующим образом: после успешного входа пользователь получает access token в формате JWT. Приложение сохраняет его в защищённое хранилище (Keychain на iOS, EncryptedSharedPreferences на Android). При каждом запросе к API приложение добавляет заголовок Authorization: Bearer <token>. Сервер API проверяет подпись JWT, извлекает claims и на основе них принимает решение о доступе — без обращения к базе данных.

По данным Google Codelabs, 2025, использование JWT в Firebase Authentication сокращает количество запросов к серверу аутентификации на 40–60% по сравнению с сессионными токенами, так как данные проверяются локально на каждом микросервисе. Это особенно важно для архитектур с высокой нагрузкой, где каждая миллисекунда задержки влияет на пользовательский опыт. При 50 000 запросов в минуту переход на JWT может сэкономить до 10 серверных инстансов, обрабатывающих introspection-запросы.

JWT vs Session Token

JWT и Session Token решают одну задачу — аутентификацию запросов — но принципиально различаются по архитектуре. Session Token — это случайная строка-идентификатор, которая ссылается на данные сессии, хранящиеся на сервере (stateful). JWT — самодостаточный токен, содержащий все данные внутри себя (stateless).

ПараметрJWTSession Token
Хранение данныхВнутри токена (самодостаточный)На сервере (сессионное хранилище)
МасштабированиеНе требует shared storageТребует Redis/DB для multi-server
Отзыв токенаСложный (нужен blacklist)Простой (удалить сессию из БД)
РазмерБольшой (500–2000 байт)Маленький (16–64 байта)
Проверка подписиКриптографическаяНет (сравнение строк)

Преимущества и недостатки JWT

JWT выигрывает в распределённых системах: микросервисы могут проверять токен локально без общего хранилища. Например, в архитектуре с пятью микросервисами каждый сервис проверяет JWT за 1–2 мс без сетевого вызова, в то время как session token требует обращения к централизованному Redis при каждом запросе, добавляя 10–30 мс задержки. Однако JWT сложно отозвать — если токен уже выпущен, он действителен до истечения срока. Session Token легко отозвать, удалив запись из БД или Redis.

Для мобильных приложений комбинированный подход — JWT с коротким сроком жизни (15–30 минут) и Refresh Token — даёт баланс между производительностью и безопасностью. JWT используется для доступа к API, а refresh token (обычно opaque) — для получения новых JWT. При компрометации JWT злоумышленник имеет доступ на 15–30 минут; при компрометации refresh token сессия блокируется через rotation и reuse detection.

Безопасность JWT

Безопасность JWT зависит от правильной реализации. Самая распространённая уязвимость — атака "alg none": злоумышленник изменяет header токена на "alg": "none", и сервер, не проверив алгоритм, принимает поддельный токен. Защита: всегда проверять, что алгоритм в header соответствует ожидаемому (RS256, ES256), и отклонять токены с alg: none.

Типовые уязвимости

Уязвимости JWT включают также: слабый секретный ключ для HMAC (перебор за минуты), утечка приватного ключа (подпись любых данных от имени сервера), хранение чувствительных данных в payload (JWT не шифрует, только подписывает), атака через JWK header injection (внедрение собственного публичного ключа). Использование проверенных библиотек — Nimbus JOSE + JWT, jjwt (io.jsonwebtoken), PyJWT — снижает риск эксплуатации этих уязвимостей.

Дополнительная мера защиты — JWK Thumbprint (RFC 7638): привязка публичного ключа к токену через отпечаток (thumbprint) в header. Если сервер сохраняет ожидаемый thumbprint для каждого клиента, атака JWK header injection становится невозможной — сервер отклоняет любой ключ, не совпадающий с зарегистрированным. OAuth Security Workshop 2025 рекомендует JWK Thumbprint как обязательную защиту для всех JWT, используемых в финансовых и медицинских приложениях.

Пример кода: работа с JWT на Kotlin

Библиотека jjwt (auth0/java-jwt) позволяет создавать и проверять JWT в Android-приложении за несколько строк. В примере ниже сервер генерирует токен с sub и role, а клиент проверяет подпись. Для безопасного хранения секретного ключа на сервере используйте переменные окружения или HSM (Hardware Security Module) — хранение ключа в коде или конфигурационном файле является грубой ошибкой безопасности.

Генерация JWT

kotlin
val secret = "my-256-bit-secret-key-here"
val token = JWT.create()
    .withSubject("user-abc-123")
    .withIssuer("auth.example.com")
    .withClaim("role", "premium_user")
    .withExpiresAt(Date(System.currentTimeMillis() + 3600000))
    .sign(Algorithm.HMAC256(secret))

// Отправка токена клиенту
println("JWT: $token")

Проверка JWT

kotlin
fun verifyToken(token: String): Boolean {
    return try {
        val decoded = JWT.require(Algorithm.HMAC256(secret))
            .withIssuer("auth.example.com")
            .build()
            .verify(token)
        // Подпись верна, claims извлечены
        println("Subject: ${decoded.subject}")
        true
    } catch (e: Exception) {
        println("Token invalid: ${e.message}")
        false
    }
}

Часто задаваемые вопросы

Можно ли хранить пароли в JWT?

Нет. JWT подписывается, а не шифруется — любой может декодировать Base64 payload и прочитать данные. Чувствительная информация (пароли, номера карт, персональные данные) должна передаваться только в зашифрованном виде через JWE (JSON Web Encryption).

Какой алгоритм подписи JWT самый безопасный?

Рекомендуется ES256 (ECDSA с P-256) — он обеспечивает эквивалентный RSA 2048-bit уровень безопасности при значительно меньшем размере подписи. Для совместимости с легаси-системами подходит RS256. HS256 (HMAC) требует безопасного обмена секретным ключом, что сложнее в распределённой архитектуре.

Как отозвать JWT до истечения срока?

JWT нельзя отозвать напрямую — он действителен до exp. Решения: использовать короткий срок жизни (15–30 минут), вести blacklist отозванных jti (JWT ID) на сервере, или связывать токены с версией секретного ключа. Refresh token при этом отзывается стандартным способом — удалением из хранилища.

Чем JWT отличается от Bearer token?

Bearer token — это концепция: любой токен, который предъявитель (bearer) может использовать для доступа. JWT — это конкретный формат токена. Bearer token может быть JWT, а может быть opaque string. JWT добавляет к концепции Bearer самодостаточность и криптографическую верификацию.

Какой размер JWT считается нормальным?

Типичный JWT с RS256 подписью занимает 500–2000 байт. Если payload содержит много кастомных claims или используется асимметричная подпись с большим ключом, размер может достигать 4–5 KB. Это значительно больше, чем session token (16–64 байта), что влияет на размер HTTP-заголовков.

Итоги

  • JWT — компактный самодостаточный токен в формате JSON с цифровой подписью
  • Структура — три части: header (алгоритм), payload (claims), signature (подпись)
  • Stateless — сервер проверяет токен без обращения к базе данных
  • JWT vs Session — JWT выигрывает в масштабировании, Session выигрывает в отзыве
  • Безопасность — защита от alg none, слабых ключей и JWK injection обязательна
  • Payload не шифруется — чувствительные данные требуют JWE
  • JWT — стандартный формат ID Token в OpenID Connect и токенов Firebase Authentication

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также