Глоссарий
Что такое JWT (JSON Web Token)? Как работает подписанный пропуск и как использовать его безопасно
JWT (JSON Web Token) — это защищённый от подделки «пропуск», который подписывает сервер. Как работают заголовок/полезная нагрузка/подпись и опасности: пропуск проверки подписи, разрешение alg:none и помещение секретов в полезную нагрузку.
«Подписанный пропуск, который сервер выдаёт вам после входа» — это и есть JWT. Разберём, как он работает, и ключевые моменты безопасного использования (без шагов атаки).
Как это работает (три части)
JWT — это header.payload.signature, соединённые через .. Заголовок и полезная нагрузка просто закодированы через base64url (не зашифрованы); только подпись создаётся с помощью секретного (или общего) ключа.
1. header
метаданные вроде алгоритма подписи. читает кто угодно
2. payload
claims вроде id пользователя и срока действия. читает кто угодно = никаких секретов
3. signature
создаётся с помощью ключа. гарантирует отсутствие подделки
Ключевой момент — содержимое «просто читаемо». Поэтому полезная нагрузка — не место для паролей или персональных данных. Ценность JWT в том, что, проверив подпись, сервер может подтвердить «я выдал этот токен, и он не был изменён».
Меры для безопасного использования
Всегда проверяйте подпись и фиксируйте alg (самое важное)
Проверяйте подпись на сервере каждый раз. Зафиксируйте принимаемый алгоритм подписи (alg) на ожидаемом значении и отклоняйте alg:none (без подписи). Не доверяйте вслепую alg, записанному в заголовке токена.
Не кладите секреты в полезную нагрузку
Считайте, что декодировать содержимое может кто угодно. Держите секреты — пароли, персональные данные, ключи API — вне неё. Включайте только claims, которые не катастрофичны при просмотре, вроде идентификаторов и разрешений.
Держите короткий срок действия и имейте способ отзыва
Делайте токены доступа короткоживущими. Слишком долгий срок действия растягивает окно ущерба при краже токена. Если нужен отзыв, сочетайте короткоживущий токен доступа с управляемым на сервере refresh/сеансом.
Используйте надёжный ключ и храните его там, где его не украдут
Сделайте ключ подписи надёжным, не переиспользуйте его и храните в безопасном месте на сервере. Защищайте и сам токен — берегите его от кражи через XSS, носите в куке с безопасными атрибутами (→ остерегайтесь кражи через XSS).
Мнение этого сайта: JWT — не универсальный сеанс
JWT часто используют, чтобы «держать состояние входа», но у него есть слабость: отзыв затруднён. Если подпись действительна и токен не истёк, сервер по сути ему доверяет, поэтому сделать так, чтобы выход или аннулирование вступали в силу немедленно, неудобно. Наша позиция: не делайте JWT долгоживущим универсальным сеансом. Сочетайте короткоживущий токен доступа с серверным, отзываемым refresh/сеансом — и вы получите и плюс JWT (дешёвую проверку), и лёгкий отзыв. Подбирайте правильное применение для него.
Слепое пятно: «оно декодировалось» — не «оно действительно»
Поскольку содержимое читаемо, кто угодно может вставить JWT в декодер JWT и осмотреть заголовок и полезную нагрузку. Но декодирование (чтение содержимого) и проверка (подтверждение подлинности) — совершенно разные вещи. Возможность декодировать ничего не гарантирует о действительности. Что решает, подлинный ли токен, — это всегда проверка подписи на сервере. Читать содержимое для отладки удобно — просто не путайте «я смог прочитать» с «оно действительно».
Читать дальше
- Инструмент: Декодер / инспектор JWT (проверить содержимое, заметить alg:none или срок действия)
- Глоссарий: что такое XSS (классический путь кражи токена) / что такое CSRF
- Обучение: как правильно выбрать MFA
FAQ
QЗашифровано ли содержимое JWT?
Нет. Заголовок и полезная нагрузка стандартного JWT «закодированы» через base64url, а не зашифрованы, поэтому любой, у кого есть токен, может прочитать содержимое. Поэтому никогда не кладите в полезную нагрузку секреты вроде паролей или персональных данных. JWT защищает не «конфиденциальность содержимого», а «то, что оно не было подделано» (целостность, через подпись).
QКакая настройка JWT самая опасная?
Не проверять подпись или принимать 'alg:none' (без подписи). Допустив это, вы позволяете злоумышленнику передать поддельный токен со свободно переписанным содержимым. Защита — всегда проверять подпись на сервере и фиксировать принимаемый алгоритм подписи (alg) на ожидаемом значении.
QДекодирование и проверка — это одно и то же?
Нет. Декодирование лишь читает содержимое, и это может сделать кто угодно (можно проверить декодером JWT). Проверка — это когда сервер с помощью секретного/открытого ключа подтверждает, что подпись действительна, токен не истёк, а издатель/аудитория верны. «Оно декодировалось» не означает «это действительный токен» — подлинность решает проверка на сервере.