JWT
JSON Web Token (рус. веб-токен в формате JSON, далее — JWT) — открытый стандарт IETF (RFC 7519, май 2015 года), определяющий компактный, самодостаточный и URL-безопасный способ представления утверждений (claims) между двумя сторонами. Информация внутри JWT цифрово подписывается (HMAC, RSA, ECDSA) либо шифруется, что позволяет проверить подлинность отправителя и целостность данных.
Что важно знать
| JSON Web Token | |
|---|---|
| англ. JSON Web Token | |
| Область использования | Веб-разработка, Информационная безопасность |
| Дата появления | май 2015[1] |
| Место появления | Инженерный совет Интернета (IETF)[2] |
| Автор понятия | Майкл Б. Джонс, Джон Брэдли, Нэт Сакимура[2] |
История
Разработка стандарта JWT велась в рамках Инженерного совета Интернета (IETF). Ключевую роль в этом процессе сыграла рабочая группа JOSE (англ. JSON Object Signing and Encryption), сформированная в 2011 году с целью разработки стандартов для защиты (подписи и шифрования) объектов в формате JSON. Первые неофициальные проекты группы начали появляться в открытом доступе к 2013 году, а в мае 2015 года был официально опубликован итоговый стандарт — RFC 7519. Его авторами выступили Майкл Б. Джонс (Microsoft), Джон Брэдли (англ. Ping Identity) и Нэт Сакимура (англ. Nomura Research Institute).
Определение
Согласно RFC 7519 JWT — это «compact, URL-safe means of representing claims to be transferred between two parties»[3]. Ключевые свойства стандарта:
- Компактность: данные кодируются в формате Base64url, поэтому токен подходит для передачи в HTTP-заголовках или URL-параметрах[4].
- Самодостаточность: токен содержит всю необходимую информацию о субъекте, что исключает необходимость хранения состояния сессии на сервере[5].
- Проверяемость: цифровая подпись (или MAC) гарантирует неизменность полезной нагрузки и подлинность издателя[6].
- Расширяемость: кроме зарегистрированных клеймов (iss, exp, sub, aud и др.) стандарт допускает публичные и приватные клеймы, что упрощает добавление пользовательских данных[7].
Структурные элементы JWT
JWT состоит из трёх Base64url-кодированных сегментов, разделённых точками («.»):
JSON-объект с метаданными токена. Основные поля:
- typ — тип токена, обычно «JWT»;
- alg — алгоритм подписи (например, HS256, RS256) либо значение «none» для неподписанных токенов. Возможность указания «none» является известной уязвимостью (атака с подменой алгоритма): злоумышленник может изменить это поле на «none» и удалить подпись. Если серверная библиотека сконфигурирована неверно и не проверяет алгоритм, она может посчитать такой токен действительным, что позволяет полностью подделать его содержимое[8].
Содержит совокупность утверждений (claims), которые делятся на зарегистрированные, публичные и частные.
- Зарегистрированные утверждения (Registered Claims): предопределённый набор утверждений, таких как iss (издатель), exp (срок действия), sub (субъект), aud (аудитория), nbf (не раньше), iat (создан) и jti (идентификатор токена).
- Публичные и частные утверждения (Public and Private Claims): пользовательские данные (например, role, userId).
Поскольку полезная нагрузка по умолчанию не шифруется, а лишь кодируется с помощью Base64url, её содержимое может быть легко прочитано любой стороной, перехватившей токен. Это создаёт риск утечки чувствительных данных, если они помещены в полезную нагрузку в открытом виде[9]. Для обеспечения конфиденциальности данных используется стандарт JSON Web Encryption (JWE).
Создаётся путём хэширования строки «Base64url(Header).Base64url(Payload)» с использованием секретного ключа (HMAC) либо закрытого ключа (RSA/ECDSA). Подпись обеспечивает:
- подтверждение издателя;
- защиту от изменения содержимого токена[10].
Одной из известных уязвимостей, связанных с подписью, является атака «Algorithm Confusion» (путаница алгоритмов). Она возникает, когда сервер некорректно валидирует алгоритм, указанный в заголовке, и позволяет переключаться между асимметричными (например, RS256) и симметричными (HS256) алгоритмами. Злоумышленник может взять публичный ключ, предназначенный для асимметричного шифрования, и использовать его как секрет для создания подписи с симметричным алгоритмом (HS256). Если сервер ожидает токен с любым из этих алгоритмов, он может ошибочно проверить подпись HS256, используя публичный ключ как секрет, и счесть поддельный токен действительным.
В итоговом виде токен выглядит как:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJleGFtcGxlIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c.
- Клиент отправляет учётные данные серверу.
- При успешной проверке сервер формирует Header и Payload, подписывает их секретом/ключом и возвращает JWT клиенту[11].
После получения JWT клиент должен безопасно его сохранить. Выбор способа хранения является критически важным аспектом безопасности, поскольку неправильный подход может привести к краже токена.
Хранение токена в веб-хранилищах, таких как `localStorage` или `sessionStorage`, считается небезопасным. Основная причина — уязвимость к атакам типа межсайтового скриптинга (XSS). Если злоумышленнику удаётся внедрить на страницу вредоносный JavaScript-код, он может получить полный доступ к хранилищу и украсть токен[12][13].
Более безопасным подходом является использование cookie с флагом `HttpOnly`. Этот флаг запрещает доступ к cookie из JavaScript, что эффективно защищает от кражи токена через XSS[14]. Однако этот метод уязвим для атак типа межсайтовой подделки запроса (CSRF), если не приняты дополнительные меры защиты[15].
Современной рекомендованной практикой является комбинированная схема с использованием двух токенов — токена доступа (access token) и токена обновления (refresh token)[12]:
- Токен доступа — короткоживущий токен (например, 5–15 минут), который хранится в памяти клиентского приложения (например, в переменной JavaScript). Это наиболее безопасный способ хранения, так как он недоступен для XSS-атак при перезагрузке страницы, но сам токен теряется при обновлении вкладки[16].
- Токен обновления — долгоживущий токен, который сохраняется в cookie с максимальными мерами защиты: `HttpOnly` (защита от XSS), `Secure` (передача только по HTTPS) и `SameSite=Strict` или `SameSite=Lax` (защита от CSRF)[17][18].
Эта архитектура минимизирует риски: даже в случае кражи короткоживущего токена доступа ущерб будет ограниченным, а наиболее ценный токен обновления надёжно защищён в cookie.
При обращении к защищённым ресурсам клиент включает JWT в заголовок
Authorization: Bearer <token>[19].
Сервер:
- проверяет подпись токена;
- удостоверяется, что exp не истёк и другие клеймы (iss, aud) валидны;
- извлекает данные пользователя и принимает решение об авторизации[20].
Поскольку JWT по своей природе являются stateless (не хранят состояние), одной из ключевых проблем является невозможность досрочного отзыва скомпрометированного токена — он остаётся действительным до истечения своего срока действия[21]. Для решения этой проблемы и повышения общего уровня безопасности применяется механизм обновления с использованием двух токенов: короткоживущего токена доступа (access token) и долгоживущего токена обновления (refresh token).
Схема работы выглядит следующим образом:
- Клиентское приложение использует токен доступа для авторизации запросов к защищённым ресурсам API.
- Когда срок действия токена доступа истекает, сервер возвращает ошибку авторизации (например, со статусом 401 Unauthorized).
- Получив ошибку, клиентское приложение отправляет запрос на специальный эндпоинт (например,
/api/refresh), не включая в него никаких данных вручную. Браузер автоматически прикрепляет к этому запросу токен обновления, который хранится в защищённой cookie с флагамиHttpOnly,SecureиSameSite. - Сервер получает токен обновления, проверяет его подлинность и валидность (например, сверяясь со списком действующих токенов в базе данных). Это позволяет централизованно отзывать сессии пользователей, просто удаляя их токен обновления[22].
- В случае успеха сервер генерирует новую пару токенов: новый токен доступа и, как правило, новый токен обновления (для реализации ротации токенов). Новый токен доступа возвращается в теле ответа, а новый токен обновления устанавливается в cookie, заменяя старый.
- Клиентское приложение сохраняет новый токен доступа (например, в памяти) и повторяет исходный запрос, который завершился ошибкой.
- Безгосударственная архитектура, упрощающее горизонтальное масштабирование[23].
- Компактный формат — меньше сетевой трафик по сравнению с SAML[4].
- Кросс-платформенность и поддержка SSO-сценариев[5].
- Проверяемость и целостность данных благодаря цифровой подписи[6].
- Невозможность досрочного отзыва токена. Поскольку JWT являются stateless, скомпрометированный токен остаётся действительным до истечения своего срока действия. Решения, такие как «чёрные списки» отозванных токенов, превращают систему в stateful, нивелируя одно из ключевых преимуществ JWT.
- Утечка данных из полезной нагрузки. По умолчанию данные в payload не шифруются, а лишь кодируются в Base64, что позволяет любой стороне, перехватившей токен, прочитать его содержимое, если в нём содержатся чувствительные данные.
- Подверженность атакам при некорректной реализации. К наиболее известным уязвимостям относятся атака с подменой алгоритма на `none` и атака «Algorithm Confusion» (путаница между асимметричными и симметричными алгоритмами).
- Риски, связанные с управлением ключами. Использование жёстко закодированных секретов в коде приложения или прошивке устройств неоднократно приводило к критическим уязвимостям (например, в оборудовании Cisco), позволяя злоумышленникам получать полный контроль над системой путём подписи собственных токенов[24].
- Увеличенный размер токена. Включение большого количества утверждений (claims) увеличивает размер токена, что повышает сетевой трафик и может создавать проблемы при хранении в cookie или localStorage.
Сферы применения
- Аутентификация и авторизация в REST-API и микросервисах[25].
- Веб- и мобильные приложения (SPA, PWA) — обмен токенами между фронтендом и бэкендом[26].
- Протоколы OAuth 2.0 и OpenID Connect (ID-, Access- и Refresh-токены).
- Безопасный обмен информацией между независимыми системами и сторонними сервисами.
Для отладки и анализа JWT используются как онлайн-сервисы, так и офлайн-приложения, которые обеспечивают безопасность при работе с конфиденциальными данными.
- JWT.io — один из самых известных онлайн-инструментов, позволяющий в браузере декодировать, верифицировать и создавать токены.
- Authgear JWT & JWE Debugger — онлайн-инструмент, который, помимо стандартных подписанных токенов (JWS), поддерживает работу с зашифрованными токенами (JWE)[27].
- DevUtils — десктопное приложение для macOS с офлайн-дебаггером JWT. Позволяет работать с токенами без отправки данных в интернет, что необходимо при работе с чувствительной информацией[28].
- Функции для работы с JWT также встроены в комплексные инструменты для тестирования API, такие как Postman, где они используются для управления токенами при отправке запросов к защищённым эндпоинтам[29].
- Node.js:
- jose — рекомендованная библиотека, строго соответствующая стандартам IETF JOSE (JWS, JWE, JWK). Отличается активной поддержкой и полным набором функций, включая шифрование токенов (JWE), что делает её предпочтительным выбором для систем с высокими требованиями к безопасности[30].
- fast-jwt — высокопроизводительная альтернатива `jsonwebtoken` с совместимым API, предназначенная для приложений, где скорость обработки токенов является критически важной[31].
- jsonwebtoken — исторически одна из самых популярных библиотек, простая в использовании. Однако по состоянию на 2025 год её разработка менее активна, и она не поддерживает шифрование (JWE), в отличие от `jose`[32].
- Python:
- PyJWT — наиболее популярная и рекомендуемая библиотека, активно поддерживается и реализует стандарт RFC 7519. Является стандартом де-факто для большинства задач[33].
- Authlib — комплексная библиотека, реализующая полный стек стандартов JOSE. Подходит для построения сложных систем аутентификации, включающих OAuth и OpenID Connect[34].
- python-jose — ранее популярная библиотека, однако на 2025 год считается слабо поддерживаемой, и её использование не рекомендуется из-за потенциальных рисков безопасности[35].
- Java:
- java-jwt (Auth0) — одна из самых популярных библиотек с удобным API, активно поддерживается компанией Auth0. Хороший выбор для большинства стандартных задач[36].
- Nimbus JOSE + JWT — мощный и гибкий фреймворк, полностью поддерживающий JWS (подпись) и JWE (шифрование). Рекомендуется для сложных сценариев, требующих максимального контроля и безопасности[37].
- JJWT — библиотека, ориентированная на простоту использования. Часто применяется в связке с фреймворком Spring Security[38].
- C# / .NET:
- System.IdentityModel.Tokens.Jwt — встроенная в .NET библиотека для создания и валидации токенов. Является стандартным решением для приложений на ASP.NET Core[39].
- Microsoft.AspNetCore.Authentication.JwtBearer — пакет для интеграции JWT-аутентификации в конвейер обработки запросов ASP.NET Core[40].
- Go:
- PHP:


