JSON Web Token

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

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 года.[1]

Структура[править | править код]

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

К примеру, для заголовка и полезной нагрузки, которые выглядят таким образом:

{
  "alg": "HS512",
  "typ": "JWT"
}
{
  "sub": "12345",
  "name": "John Gold",
  "admin": true
}

Получим следующее компактное представление (переводы строки добавлены для наглядности):

eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJKb2huIEdvbGQiLCJhZG1pbiI6dHJ1ZX0.
LIHjWCBORSWMEibq-tnT8ue_deUqZx1K0XxCOXZRrBI

Заголовок[править | править код]

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

Обязательный ключ здесь только один:

  • alg: алгоритм, используемый для подписи/шифрования (в случае не подписанного JWT используется значение "none").

Необязательные ключи:

  • typ: тип токена (type). Используется в случае, когда токены смешиваются с другими объектами, имеющими JOSE заголовки. Должно иметь значение "JWT".
  • cty: тип содержимого (content type). Если в токене помимо зарегистрированных служебных ключей есть пользовательские, то данный ключ не должен присутствовать. В противном случае должно иметь значение "JWT"[2]

Полезная нагрузка[править | править код]

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

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

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

Access и refresh токены[править | править код]

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

Схема работы[править | править код]

Как правило, при использовании JSON токенов в клиент-серверных приложениях реализована следующая схема:

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

Преимущества[править | править код]

JWT имеет ряд преимуществ над куки:

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

Возможные атаки[править | править код]

Удаление подписи[править | править код]

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

CSRF[править | править код]

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

XSS[править | править код]

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

JWS[править | править код]

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

Поддерживаемые алгоритмы подписи[править | править код]

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

Обязательный для поддержки всеми реализациями алгоритм:

Рекомендованные алгоритмы:

Также поддерживаются вариации рекомендованных алгоритмов с использованием SHA-384 и SHA-512 соответственно:

  • HS384, HS512
  • RS384, RS512
  • ES384, ES512

Аббревиатуры курсивом - названия, использующиеся в JSON токенах, описанные спецификацией JWA (RFC 7518)[11]

Структура заголовка[править | править код]

В случае подписанного 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 certi cate SHA-1 fingerprint).
  • crit: Массив строк с названиями ключей данного заголовка, которые должны обрабатываться парсером JWT. Если должны быть обработаны все ключи, то не используется (critical).[12]

Реализации[править | править код]

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

Примечания[править | править код]

  1. JWT Handbook v0.13.0, с.6-7 (англ.). auth0.com. Проверено 11 декабря 2017.
  2. Bradley, John, Sakimura, Nat, Jones, Michael. JSON Web Token (JWT), с. 11 (англ.). tools.ietf.org. Проверено 20 декабря 2017.
  3. Bradley, John, Sakimura, Nat, Jones, Michael. JSON Web Token (JWT), c. 9-10 (англ.). tools.ietf.org. Проверено 20 декабря 2017.
  4. JWT Handbook v0.13.0, c. 18 (англ.). auth0.com. Проверено 20 декабря 2017.
  5. Ryan Boyd. Getting Started with OAuth 2.0. — O'Reilly media, 2012. — С. 56.
  6. JWT Handbook v0.13.0, с. 9-11 (англ.). auth0.com. Проверено 21 декабря 2017.
  7. Justin Richer and Antonio Sanso. OAuth 2 in Action. — Manning Publications, 2017. — С. 252-253. — 360 с. — ISBN 9781617293276.
  8. JWT Handbook v0.13.0, с. 9 (англ.). auth0.com. Проверено 21 декабря 2017.
  9. JWT Handbook v0.13.0, с. 10 (англ.). auth0.com. Проверено 21 декабря 2017.
  10. JWT Handbook v0.13.0, с. 11-12 (англ.). auth0.com. Проверено 20 декабря 2017.
  11. Bradley, John, Sakimura, Nat, Jones, Michael. JSON Web Token (JWT), с. 16 (англ.). tools.ietf.org. Проверено 20 декабря 2017.
  12. Bradley, John, Sakimura, Nat, Jones, Michael. JSON Web Signature (JWS), c. 9-14 (англ.). tools.ietf.org. Проверено 20 декабря 2017.
  13. auth0.com. JWT.IO (англ.). jwt.io. Проверено 20 декабря 2017.

Ссылки[править | править код]