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

JWT (JSON Web Token) состоит из трёх логических частей, разделённых точками:

header.payload.signature

Каждая из этих частей кодируется в формате Base64Url и играет строго определённую роль в процессе формирования и проверки токена.


Заголовок JWT содержит метаданные о самом токене и алгоритме подписи.

Типичная структура:

{
  "alg": "HS256",
  "typ": "JWT"
}

Поле alg

Определяет алгоритм, используемый для создания подписи.

Наиболее распространённые варианты:

  • HS256 — HMAC с SHA-256 (симметричный ключ)
  • RS256 — RSA с SHA-256 (асимметричный ключ)
  • ES256 — ECDSA с SHA-256

Выбор алгоритма влияет на всю криптографическую модель системы. Например, HS256 использует один секрет для подписи и проверки, тогда как RS256 разделяет приватный и публичный ключи.

Поле typ

Указывает тип токена. В JWT всегда фиксированное значение:

"typ": "JWT"

Payload (полезная нагрузка)

Payload содержит утверждения (claims) — данные, которые передаются внутри токена.

Структура не фиксирована и может включать как стандартные, так и пользовательские поля.

Стандартные claims

  • iss (issuer) — издатель токена
  • sub (subject) — субъект (например, ID пользователя)
  • aud (audience) — получатель токена
  • exp (expiration time) — время истечения
  • nbf (not before) — токен не действителен до указанного времени
  • iat (issued at) — время создания
  • jti (JWT ID) — уникальный идентификатор токена

Пример:

{
  "sub": "user123",
  "name": "Ivan Petrov",
  "role": "admin",
  "iat": 1710000000,
  "exp": 1710003600
}

Пользовательские claims

В payload можно добавлять произвольные данные:

{
  "userId": 42,
  "permissions": ["read", "write"],
  "theme": "dark"
}

Payload не шифруется, а только кодируется. Это означает, что любые данные внутри JWT доступны для чтения после декодирования Base64Url. Поэтому хранить чувствительную информацию (пароли, секреты) внутри payload недопустимо.


Signature (подпись)

Подпись обеспечивает целостность токена и подтверждает, что данные не были изменены.

Формирование подписи происходит на основе:

HMACSHA256(
  base64Url(header) + "." + base64Url(payload),
  secret
)

Для RSA-алгоритмов используется приватный ключ:

RSASHA256(
  data,
  privateKey
)

Подпись выполняет две ключевые функции:

  • проверка подлинности источника токена
  • защита от изменения header и payload

Любая модификация даже одного символа в первых двух частях делает подпись недействительной.


Кодирование JWT

Каждая часть JWT кодируется в Base64Url без padding (=).

Финальная строка имеет вид:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiJ1c2VyMTIzIiwicm9sZSI6ImFkbWluIn0.
K8Q7f9p2h3mL9s8dKJH1aVx0cQeZ...

Формирование JWT с использованием Jsrsasign

Библиотека Jsrsasign предоставляет инструменты для создания и проверки JWT без необходимости ручной реализации криптографических операций.

Пример создания токена:

const header = { alg: "HS256", typ: "JWT" };

const payload = {
  sub: "user123",
  role: "admin",
  iat: KJUR.jws.IntDate.get("now"),
  exp: KJUR.jws.IntDate.get("now + 1hour")
};

const secret = "my-secret-key";

const token = KJUR.jws.JWS.sign(
  "HS256",
  JSON.stringify(header),
  JSON.stringify(payload),
  secret
);

Здесь:

  • KJUR.jws.JWS.sign формирует JWT целиком
  • библиотека автоматически кодирует header и payload
  • создаёт подпись по указанному алгоритму

Разбор JWT через Jsrsasign

Для декодирования используется функция:

const isValid = KJUR.jws.JWS.verifyJWT(token, secret, { alg: ["HS256"] });

const parsed = KJUR.jws.JWS.parse(token);

Результат parse содержит:

  • header
  • payload
  • signature
  • rawSegments

Пример доступа к данным:

console.log(parsed.headerObj);
console.log(parsed.payloadObj);

Структурные особенности и важные свойства

JWT имеет несколько ключевых характеристик, вытекающих из его структуры:

1. Самодостаточность

Payload содержит всю необходимую информацию для авторизации без обращения к базе данных.

2. Отсутствие шифрования

Base64Url — это кодирование, а не защита. Любой может прочитать payload.

3. Криптографическая целостность

Signature гарантирует, что токен не был изменён после создания.

4. Статичность

После создания JWT не может быть изменён без нарушения подписи. Это делает невозможным обновление payload без генерации нового токена.


Ошибки при работе со структурой JWT

Часто встречаются типичные проблемы:

  • использование слабого алгоритма (например, none)
  • хранение чувствительных данных в payload
  • неправильная проверка подписи
  • игнорирование exp, что приводит к вечным токенам
  • несогласованность алгоритма между созданием и проверкой

Взаимодействие частей JWT в процессе проверки

При валидации происходит последовательность:

  1. Разделение токена на три части
  2. Декодирование header и payload
  3. Пересчёт подписи на основе первых двух частей
  4. Сравнение вычисленной подписи с полученной
  5. Проверка временных ограничений (exp, nbf)

Любое несоответствие приводит к отклонению токена.


Формат и ограничения структуры

JWT строго следует формату:

base64Url(header).base64Url(payload).base64Url(signature)

Любые дополнительные точки, пробелы или символы делают токен невалидным.

Размер токена зависит от:

  • сложности payload
  • длины ключей подписи
  • выбранного алгоритма

Роль структуры JWT в безопасности

Безопасность JWT полностью опирается на разделение структуры:

  • header задаёт способ проверки
  • payload хранит данные без защиты конфиденциальности
  • signature обеспечивает неизменность

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