Что такое JSON Web Token (JWT)?
Получите четкое понимание основ JSON Web Token (JWT) за 5 минут.
JSON Web Token (JWT) широко используется в современных веб-приложениях и открытых стандартах, таких как OpenID Connect, облегчая аутентификацию и авторизацию. Хотя официальный RFC 7519 служит важным справочником, новичкам будет сложно его понять. В этой статье мы сосредоточимся на основных концепциях JWT и изложим их простым языком с примерами.
Почему нам нужен JWT?
Сегодня довольно распространено использовать JSON для обмена данными между двумя сторонами. Рассмотрим JSON-объект, представляющий пользователя:
sub
- это сокращение от "subject", который является стандартной претензией в OpenID Connect для представления идентификатора пользователя (ID пользователя).
Как мы можем гарантировать целостность этого JSON-объекта? Другими словами, как нам убедиться, что данные не были подделаны во время передачи? Распространенным решением является использование цифровых подписей. Например, мы можем использовать криптографию с открытым ключом: сервер подписывает JSON-объект своим закрытым ключом, а клиент может проверить подпись открытым ключом сервера.
В двух словах, JWT предлагает стандартизированный подход к представлению JSON-объекта и его подписи.
Формат JWT
Поскольку существует множество алгоритмов для создания цифровых подписей, необходимо указать алгоритм, используемый для подписи JWT. Это достигается путем создания JSON-объекта:
alg
- это сокращение от "algorithm", аtyp
- сокращение от "type".
Обычно typ
устанавливается на JWT
в верхнем регистре. В нашем примере alg
- это HS256
, что означает HMAC-SHA256 (мы вскоре объясним это) и указывает, что мы используем этот алгоритм для создания подписи.
Теперь у нас есть все ингредиенты для JWT:
- Заголовок JSON: Алгоритм и тип
- Payload JSON: Фактические данные
- Подпись: Подпись, охватывающая заголовок и полезную нагрузку
Однако некоторые символы, такие как пробелы и переносы строк, не дружелюбны к сетевой передаче. Поэтому заголовок и полезная нагрузка должны быть Base64URL-кодированы. Типичный JWT выглядит так:
.
служит разделителем.
Соберем все вместе и создадим JWT:
Заголовок
JSON: {"alg":"HS256","typ":"JWT"}
Base64URL закодировано: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload
JSON: {"sub":"foo","name":"John Doe"}
Base64URL закодировано: eyJzdWIiOiJmb28iLCJuYW1lIjoiSm9obiBEb2UifQ
Подпись
В HMAC-SHA256 подпись создается с секретом:
Например, с секретом как some-great-secret
, подпись становится: XM-XSs2Lmp76IcTQ7tVdFcZzN4W_WcoKMNANp925Q9g
.
JWT
Финальный JWT:
Этот действительный JWT может быть проверен любой стороной, владеющей секретом.
Выберите алгоритм подписи
Как упоминалось ранее, существует множество алгоритмов для создания цифровых подписей. Мы использовали HS256
в качестве примера, но он может быть недостаточно сильным, поскольку секрет должен быть разделен между сторонами (например, клиентом и сервером).
В реальных условиях клиентами могут быть публичные приложения, такие как React приложения, которые не могут сохранить секрет. Следовательно, предпочтительный подход заключается в использовании криптографии с открытым ключом (т. е. асимметричной криптографии) для подписи JWT. Начнем с самого популярного алгоритма: RSA.
RSA
RSA, асимметричн ый алгоритм, использует пару ключей: открытый ключ и закрытый ключ. Открытый ключ используется для проверки подписи, а закрытый ключ - для подписи.
Заголовок JSON для RSA выглядит так:
RS256
означает RSA-SHA256, что значит, что подпись создается с использованием алгоритма RSA и хеш-функции SHA256. Вы также можете использоватьRS384
иRS512
для создания подписей с функциями хеширования SHA384 и SHA512 соответственно.
Подпись создается с использованием закрытого ключа:
Снова, мы можем собрать эти части, чтобы создать JWT, и финальный JWT выглядит так:
Теперь клиент может проверить подпись, не зная закрытого ключа.
ECDSA
Хотя RSA широко принят, он страдает от больших размеров подписи, иногда превышающих совокупный размер заголовка и полезной нагрузки. Эллиптический алгоритм цифровой подписи по кривой (ECDSA) - это другой асимметричный алгоритм, который может создавать более компактные подписи и является более производительным.
Чтобы сгенерировать закрытый ключ для ECDSA, нам нужно выбрать кривую. Это выходит за рамки этой статьи, но вы можете найти больше информации здесь.
Заголовок JSON для ECDSA выглядит так:
ES256
означает ECDSA-SHA256, что означает, что подпись создается с использованием алгоритма ECDSA и хеш-функции SHA256. Вы также можете использоватьES384
иES512
для создания подписей с функциями хеширования SHA384 и SHA512 соответственно.
Подпись создается с использованием закрытого ключа:
Финальный JWT сохраняет ту же структуру, что и RSA, но с значительно более короткой подписью:
Проверьте JWT
Проверка JWT проста, так как это обратный процесс создания JWT:
- Разделите JWT на три части (заголовок, полезная нагрузка и подпись), используя разделитель
.
. - Расшифруйте заголовок и полезную нагрузку с помощью Base64URL.
- Проверьте подпись с помощью алгоритма, указанного в загол овке, и открытого ключа (для асимметричных алгоритмов).
Существует много библиотек, которые доступны для помощи в проверке JWT, таких как jose для Node.js и веб-браузеров.
Заключение
В этой статье мы кратко объяснили основные концепции JWT, а также дали обзор того, как его создать и проверить. Многие детали остаются неизведанными, и мы охватим их в будущих статьях.
Logto использует открытые стандарты, такие как JWT и OpenID Connect, чтобы обеспечить безопасность ваших приложений и API с упрощенными рабочими процессами для каждого разработчика. Если вы заинтересованы, вы можете попробовать его бесплатно (кредитная карта не требуется).