JSON Web Token (JWT) — открытый стандарт (RFC 7519) для создания токенов доступа, основанный на формате JSON. Как правило, используется для передачи данных после аутентификации в клиент-серверных приложениях. Токены создаются сервером, подписываются секретным ключом и передаются клиенту, который в дальнейшем использует данный токен для подтверждения подлинности аккаунта.

История В 2011 году была сформирована группа JOSE (JSON Object Signing and Encryption group), целью которой была стандартизация механизма защиты целостности, шифрования, а также формата ключей и алгоритмов идентификации для обеспечения совместимости служб безопасности, использующих формат JSON. К 2013 году в открытом доступе появились неофициальные наброски и примеры использования идей данной группы, которые позже стали стандартами RFC: JWT, JWS, JWE, JWK и JWA.

Официально JWT был стандартизован группой IETF в мае 2015 года.

Структура Токен JWT состоит из трёх частей: заголовка (header), полезной нагрузки (payload) и подписи или данных шифрования. Первые два элемента — это JSON-объекты определённой структуры. Третий элемент вычисляется на основании первых и зависит от выбранного алгоритма (в случае использования неподписанного JWT может быть опущен). Токены могут быть перекодированы в компактное представление (JWS/JWE Compact Serialization): к заголовку и полезной нагрузке применяется алгоритм кодирования Base64-URL, после чего добавляется подпись и все три элемента разделяются точками («.»). К примеру, для заголовка и полезной нагрузки, которые выглядят следующим образом:{ "alg": "HS512", "typ": "JWT"

"sub": "12345", "name": "John Gold", "admin": true }получим следующее компактное представление (переносы строки добавлены для наглядности):eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJKb2huIEdvbGQiLCJhZG1pbiI6dHJ1ZX0K. LIHjWCBORSWMEibq-tnT8ue_deUqZx1K0XxCOXZRrBI

Заголовок В заголовке указывается необходимая информация для описания самого токена.

Обязательный ключ здесь только один: alg: алгоритм, используемый для подписи/шифрования (в случае неподписанного JWT используется значение «none»). Необязательные ключи: typ: тип токена (type). Используется в случае, когда токены смешиваются с другими объектами, имеющими JOSE заголовки. Должно иметь значение «JWT». cty: тип содержимого (content type). Если в токене помимо зарегистрированных служебных ключей есть пользовательские, то данный ключ не должен присутствовать. В противном случае должно иметь значение «JWT»

Полезная нагрузка В данной секции указывается пользовательская информация (например, имя пользователя и уровень его доступа), а также могут быть использованы некоторые служебные ключи. Все они являются необязательными: iss: чувствительная к регистру строка или URI, которая является уникальным идентификатором стороны, генерирующей токен (issuer). sub: чувствительная к регистру строка или URI, которая является уникальным идентификатором стороны, о которой содержится информация в данном токене (subject). Значения с этим ключом должны быть уникальны в контексте стороны, генерирующей JWT. aud: массив чувствительных к регистру строк или URI, являющийся списком получателей данного токена. Когда принимающая сторона получает JWT с данным ключом, она должна проверить наличие себя в получателях — иначе проигнорировать токен (audience). exp: время в формате Unix Time, определяющее момент, когда токен станет невалидным (expiration). nbf: в противоположность ключу exp, это время в формате Unix Time, определяющее момент, когда токен станет валидным (not before). jti: строка, определяющая уникальный идентификатор данного токена (JWT ID). iat: время в формате Unix Time, определяющее момент, когда токен был создан. iat и nbf могут не совпадать, например, если токен был создан раньше, чем время, когда он должен стать валидным (issued at).

Использование в клиент-серверных приложениях

Access- и refresh-токены Access-токен — это токен, который предоставляет доступ его владельцу к защищённым ресурсам сервера. Обычно он имеет короткий срок жизни и может нести в себе дополнительную информацию, такую как IP-адрес стороны, запрашивающей данный токен. Refresh-токен — это токен, позволяющий клиентам запрашивать новые access-токены по истечении их времени жизни. Данные токены обычно выдаются на длительный срок.

Схема работы Как правило, при использовании JSON-токенов в клиент-серверных приложениях реализована следующая схема: Клиент проходит аутентификацию в приложении (к примеру, с использованием логина и пароля). В случае успешной аутентификации сервер отправляет клиенту access- и refresh-токены. При дальнейшем обращении к серверу клиент использует access-токен. Сервер проверяет токен на валидность и предоставляет клиенту доступ к ресурсам. В случае, если access-токен становится не валидным, клиент отправляет refresh-токен, в ответ на который сервер предоставляет два обновлённых токена. В случае, если refresh-токен становится не валидным, клиент опять должен пройти процесс аутентификации (п. 1).

Преимущества JWT имеет ряд преимуществ по сравнению с подходом хранения выданных сессий на сервере и в куки на стороне клиента: При использовании JWT не требуется хранение дополнительных данных о выданных сессиях: все, что должен сделать сервер — это проверить подпись. Сервер может не заниматься созданием токенов, а предоставить это внешним сервисам. В JSON-токенах можно хранить дополнительную полезную информацию о пользователях. Как следствие — более высокая производительность. В случае c куки иногда необходимо осуществлять запросы для получения дополнительной информации. При использовании JWT эта информация может быть передана в самом токене. JWT делает возможным предоставление одновременного доступа к различным доменам и сервисам.

Возможные атаки

Удаление подписи JWT-токен состоит из трёх частей, которые кодируются независимо друг от друга. Таким образом, становится возможным удалить подпись из токена и изменить заголовок, сделав JWT неподписанным. Если на сервере не стоит проверка на наличие подписи у токена, то злоумышленник может указывать собственные значения в полезной нагрузке. Проблема решается простым отбрасыванием неподписанных объектов.

CSRF Одним из методов борьбы с CSRF является добавление специальных заголовков с зашифрованной информацией, подтверждающей отправку запроса с доверенного сервера. Таким образом, если JWT используется не в качестве cookie, CSRF-атака становится невозможной.

XSS JSON-токены могут храниться в браузере двумя способами: в DOM-хранилище или в cookie. В первом случае система может быть подвержена XSS-атаке, так как JavaScript имеет доступ к DOM-хранилищу и злоумышленник может извлечь оттуда токен для дальнейшего использования от имени пользователя. При использовании cookie можно выставить HttpOnly-флаг, который предотвращает доступ JavaScript к хранилищу. Таким образом, злоумышленник не сможет извлечь токен и приложение становится защищенным от XSS.

JWS Подписанные JSON-токены описываются JWS-спецификацией (RFC 7515).

Поддерживаемые алгоритмы подписи Подпись заголовка и полезной нагрузки производится следующими алгоритмами:

Обязательный для поддержки всеми реализациями алгоритм: HMAC с использованием SHA-256 (HS256) Рекомендованные алгоритмы: RSASSA PKCS1 v1.5 с использованием SHA-256 (RS256) ECDSA с использованием P-256 и SHA-256 (ES256) Также поддерживаются вариации рекомендованных алгоритмов с использованием SHA-384 и SHA-512 соответственно: HS384, HS512 RS384, RS512 ES384, ES512 Аббревиатуры курсивом — названия, использующиеся в JSON-токенах, описанные спецификацией JWA (RFC 7518)

Структура заголовка В случае подписанного JWT в заголовок могут быть добавлены дополнительные ключи: jku: URI на набор открытых ключей в JSON-формате, используемых для подписи данного токена (JSON Web Key Set URL). jwk: Ключ, используемый для подписи данного токена (JSON Web Key). kid: Уникальный идентификатор используемого ключа для случая, когда указывается набор ключей (Key ID). x5u: URI на набор сертификатов X.509. Первый сертификат в наборе должен являться тем, который использовался для подписи данного токена (X.509 URL). x5c: Массив сертификатов X.509 в формате JSON, использованных для подписи данного токена (X.509 certifcate chain). x5t: Цифровой отпечаток SHA1 сертификата X.509 (X.509 certificate SHA-1 fingerprint). crit: Массив строк с названиями ключей данного заголовка, которые должны обрабатываться парсером JWT. Если должны быть обработаны все ключи, то не используется (critical).

Реализации Реализации JWT существуют в следующих языках программирования и фреймворках: Clojure, .NET, Go, Haskell, Python, Java, JavaScript, Lua, Perl, PHP, Ruby, Rust, Scala, D, C++, Delphi, Erlang, Common Lisp и Elixir.

Примечания

Ссылки jwt.io — specialized website about JWT with tools and documentation, maintained by Auth0 IETF official website JWT Handbook by Sebastián Peyrott

Категория:Аутентификация Категория:Веб-программирование Категория:Стандарты