JSON Web Token
(
JWT
) — это открытый стандарт (
) для создания токенов доступа, основанный на формате
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 делает возможным предоставление одновременного доступа к различным
доменам
и сервисам.
Возможные атаки
Удаление подписи
JSON-токен состоит из трех частей, которые кодируются независимо друг от друга. Таким образом, становится возможным удалить подпись из токена и изменить заголовок, сделав JWT неподписанным. Если на сервере не стоит проверка на наличие подписи у токена, то злоумышленник может указывать собственные значения в полезной нагрузке. Проблема решается простым отбрасыванием неподписанных объектов.
CSRF
Одним из методов борьбы с
CSRF
является добавление специальных заголовков с зашифрованной информацией, подтверждающей отправку запроса с доверенного сервера. Таким образом, если JWT используется не в качестве куки, CSRF-атака становится невозможной.
XSS
JSON-токены могут храниться в браузере двумя способами: в
DOM-хранилище
или в
куки
. В первом случае система может быть подвержена
XSS
-атаке, так как
JavaScript
имеет доступ к DOM-хранилищу и злоумышленник может извлечь оттуда токен для дальнейшего использования от имени пользователя. При использовании куки можно выставить HttpOnly-флаг, который предотвращает доступ JavaScript к хранилищу. Таким образом, злоумышленник не сможет извлечь токен и приложение становится защищенным от XSS.
JWS
Подписанные JSON-токены описываются JWS-спецификацией (
).
Поддерживаемые алгоритмы подписи
Подпись заголовка и полезной нагрузки производится следующими алгоритмами:
Обязательный для поддержки всеми реализациями алгоритм:
Рекомендованные алгоритмы:
Также поддерживаются вариации рекомендованных алгоритмов с использованием SHA-384 и SHA-512 соответственно:
-
HS384, HS512
-
RS384
,
RS512
-
ES384
,
ES512
Аббревиатуры курсивом — названия, использующиеся в JSON-токенах, описанные спецификацией JWA (
)
Структура заголовка
В случае подписанного 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
,
Erlang
,
Common Lisp
и
Elixir
.
Примечания
-
(англ.)
. auth0.com. Дата обращения: 11 декабря 2017.
15 июля 2018 года.
-
Bradley, John, Sakimura, Nat, Jones, Michael.
(англ.)
. tools.ietf.org. Дата обращения: 20 декабря 2017.
16 июня 2019 года.
-
Bradley, John, Sakimura, Nat, Jones, Michael.
(англ.)
. tools.ietf.org. Дата обращения: 20 декабря 2017.
16 июня 2019 года.
-
(англ.)
. auth0.com. Дата обращения: 20 декабря 2017.
15 июля 2018 года.
-
Ryan Boyd.
. — O'Reilly media, 2012. — С.
.
-
(англ.)
. auth0.com. Дата обращения: 21 декабря 2017.
15 июля 2018 года.
-
Justin Richer and Antonio Sanso.
OAuth 2 in Action. — Manning Publications, 2017. — С. 252—253. — 360 с. —
ISBN 9781617293276
.
-
(англ.)
. auth0.com. Дата обращения: 21 декабря 2017.
15 июля 2018 года.
-
(англ.)
. auth0.com. Дата обращения: 21 декабря 2017.
15 июля 2018 года.
-
(англ.)
. auth0.com. Дата обращения: 20 декабря 2017.
15 июля 2018 года.
-
Bradley, John, Sakimura, Nat, Jones, Michael.
(англ.)
. tools.ietf.org. Дата обращения: 20 декабря 2017.
16 июня 2019 года.
-
Bradley, John, Sakimura, Nat, Jones, Michael.
(англ.)
. tools.ietf.org. Дата обращения: 20 декабря 2017.
12 сентября 2017 года.
-
auth0.com.
(англ.)
. jwt.io. Дата обращения: 20 декабря 2017.
25 октября 2017 года.
Ссылки
-
— specialized website about JWT with tools and documentation, maintained by
-
- IETF official website
-
- JWT Handbook by Sebastián Peyrott