Какие данные допустимо хранить в payload JWT-токена?

Ответ

В полезной нагрузке (payload) JWT-токена хранятся утверждения (claims) — данные о пользователе и метаданные токена. Важно: JWT подписывается, но не шифруется по умолчанию (если не используется JWE), поэтому его содержимое легко декодируется.

Рекомендуемые данные (стандартные и публичные claims):

{
  "sub": "user123",          // Subject - идентификатор пользователя (обязательный)
  "iat": 1516239022,         // Issued At - время выпуска токена
  "exp": 1516242622,         // Expiration Time - срок действия
  "name": "John Doe",       // Имя пользователя
  "roles": ["user", "editor"], // Роли или права доступа
  "email": "john@example.com"
}

Что можно, но с осторожностью:

  • Идентификаторы сессии, ID команды — неконфиденциальные метаданные.
  • Объем данных должен быть минимальным, так как токен передается в заголовке каждого HTTP-запроса.

Что хранить НЕЛЬЗЯ:

  • Пароли, секретные ключи, токены доступа.
  • Конфиденциальные персональные данные (номер паспорта, кредитной карты).
  • Критичную бизнес-логику, которую нельзя раскрывать клиенту.

Лучшие практики:

  1. Используйте короткоживущие Access Tokens с минимальным набором claims.
  2. Для конфиденциальных данных используйте JWE (JSON Web Encryption) или храните их только на сервере, возвращая в токене ссылочный ID.
  3. Всегда передавайте JWT по HTTPS.

Ответ 18+ 🔞

Ага, слушай, вот эта вся тема с JWT, она ж вроде как прозрачная, а народ умудряется накосячить так, что мама не горюй. Смотри, разжую.

Представь, что твой JWT-токен — это не зашифрованная записка, а открытка. Да, её подписали, чтобы подделку заметить, но любой, у кого она в руках, может прочитать, что там написано. Просто взять и декодировать base64, и всё, ёпта. Никакой магии.

Так что класть туда нужно только то, что не стыдно написать на заборе. Вот пример, как это обычно выглядит у адекватных людей:

{
  "sub": "user123",          // Это типа "кто?" — главный идентификатор юзера
  "iat": 1516239022,         // Когда токен выписали (issued at)
  "exp": 1516242622,         // Когда он сдохнет (expiration time). Без этого — пипец.
  "name": "John Doe",       // Имя, можно
  "roles": ["user", "editor"], // Роли — самое то, чтобы на бэкенде проверять права
  "email": "john@example.com"  // Почта, ок
}

Можно ещё какую-нибудь свою хуйню добавить, типа team_id или session_ref, но главный принцип — чем меньше, тем лучше. Токен же в каждом запросе летает в заголовке, ты его на каждый чих таскаешь. Напихаешь туда трёхтомник «Война и мир» — трафик раздуешь, да и смысла ноль.

А теперь, блядь, самое важное — что туда пихать НЕ НАДО, даже если очень хочется:

  • Пароли, секретные ключи, приватные API-токены. Это же пиздец, товарищ! Ты их в открытку вписываешь!
  • Паспортные данные, номера кредиток, медкарты. Это ты кому, блядь, собрался показывать? Всему интернету?
  • Какую-то нашу тайную бизнес-логику, которую клиенту знать вообще не положено. Не делай из токена справочник по внутреннему устройству системы.

Как делать правильно, чтобы не было мучительно больно:

  1. Делай Access Tokens короткоживущими. Пусть живут минуты, а не месяцы. Для обновления есть refresh tokens, которые хранятся надёжнее.
  2. Если реально нужно передать что-то секретное (хотя это красный флаг), то используй JWE (JSON Web Encryption), это когда токен ещё и шифруется. Но это уже сложнее.
  3. Идеальный подход: на сервере в базе лежат все детали пользователя, а в токене — только его user_id (sub) и, может, роли. По user_id всё остальное достал. Клиенту не нужно знать твой размер обуви.
  4. И, само собой, всегда используй HTTPS. Отправлять JWT по HTTP — это как отправить ту самую открытку с паролями почтовым голубем через площадь. Все прочитают, блядь.

Короче, думай головой. Токен — это не сейф, а скорее пропуск с фотографией и штампом «действителен до». Всё, что на этом пропуске написано, видят все охранники на пути.