Долгое время, с тех пор как я начал изучать веб-токи JSON, я задавался вопросом, как происходит проверка подлинности JWT? Я понял, что мы подписываем токен и используем этот подписанный токен для подтверждения его подлинности. Но мне все равно было интересно узнать больше, и я задавался вопросом, почему мы никогда не вдавались в подробности этого процесса.
Надеюсь, эта статья поможет вам понять, как работает подписание JWT и как мы проверяем подписанный токен.
- Почему же нам не нужно знать, как работают подписание и валидация? 🤔
- Что представляет собой JSON Web Token? 🤔
- Сегмент заголовка
- Сегмент полезной нагрузки
- Сегмент крипто/подписи
- Итак, как работает подписание и проверка? 🤔
- Процесс подписания
- Подписание входных данных
- Хеширование
- Шифрование
- Процесс валидации
- Декодирование утверждений
- Хеширование (снова)
- Расшифровка
- Сравнение хэшей
- Проверка утверждений токена
- Заключение
- Приложение
Почему же нам не нужно знать, как работают подписание и валидация? 🤔
Прежде чем мы начнем, давайте быстро изложим некоторые сведения о JSON Web Tokens.
JSON Web Tokens (или JWT) — это компактный, безопасный для URL способ передачи фрагментов данных между двумя сторонами. Они определены открытым стандартом (RFC 7519) и в целом состоят из трех сегментов (заголовок, полезная нагрузка и криптосегмент). JWT подписываются при генерации, и те же самые подписанные JWT проверяются при получении, чтобы убедиться, что они не были изменены при передаче.
Для более детального ознакомления я настоятельно рекомендую вам прочитать мой блог о JSON Web Token (JWT) и о том, почему мы их используем.
Итак, почему же большинство ресурсов, посвященных JWT, просто говорят «а затем вы подписываете и подтверждаете» и оставляют все как есть? Ответ заключается в абстракции. Например, когда вы водите автомобиль, вам не нужно знать, как работает двигатель, и вы не настраиваете его, чтобы добиться наилучшей производительности автомобиля.
Мы верим, что производители использовали свой опыт и приложили все усилия, чтобы сделать что-то полезное для нас. Точно так же вам не нужно знать точный процесс подписания и проверки JWT, чтобы эффективно использовать их для аутентификации и авторизации ваших приложений и API.
Обратите внимание, что, хотя обычно не следует подписывать и подтверждать токены самостоятельно, знание того, как это работает, может помочь вам чувствовать себя более комфортно при использовании JWT. Эксперты, такие как поставщики идентификационных данных и платформы Identity-as-a-Service, такие как Auth0, Okta и Microsoft Active Directory, гарантируют, что этот процесс прост.
Так что если вам все еще интересно (как и мне) узнать, как это работает, читайте дальше.
Что представляет собой JSON Web Token? 🤔
Для более подробного описания я настоятельно рекомендую вам прочитать мой блог о JSON Web Token (JWT) и о том, почему мы их используем, но давайте сделаем краткий обзор.
JSON Web Token состоит из трех сегментов строк, безопасных для URL-адресов, объединенных периодами .
Сегмент заголовка
Первый сегмент — это сегмент заголовка:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
Сегмент заголовка — это объект JSON, содержащий алгоритм подписания и тип токена. Он закодирован в base64Url.
В декодированном виде он выглядит примерно так:
{
"alg": "RS256",
"typ": "JWT"
}
Сегмент полезной нагрузки
Второй сегмент — это сегмент полезной нагрузки:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0
Это объект JSON, содержащий утверждения данных, которые содержат информацию о пользователе и другую информацию, связанную с аутентификацией. Это информация, которую JWT передает от одного объекта к другому. Она также кодируется base64Url. Требования к данным могут выглядеть следующим образом:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022
}
Сегмент крипто/подписи
Последний сегмент — это сегмент крипто/подписи. JWT подписываются, чтобы их нельзя было изменить при передаче. Когда сервер авторизации выдает токен, он подписывает его с помощью ключа.
Когда клиент получает идентификационный токен, он также проверяет подпись с помощью ключа. В зависимости от алгоритма подписи используемый ключ может быть разным. Если используется асимметричный алгоритм подписания, то для подписи и проверки используются разные ключи. В этом случае только сервер авторизации имеет возможность подписывать токены.
Итак, как работает подписание и проверка? 🤔
Процесс подписания
В этой статье я буду использовать алгоритм подписи RS256. RS256 — это алгоритм цифровой подписи RSA с SHA-256. SHA-256 — это алгоритм асимметричной криптографии, который использует пару ключей: открытый ключ и закрытый ключ для шифрования и дешифрования. Здесь закрытый ключ используется сервером авторизации, а открытый ключ — приложением, получающим токен, для его подтверждения.
Подписание входных данных
Сначала мы берем первые два сегмента JWT (заголовок и полезную нагрузку). Это будет выглядеть примерно так:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0
В основном это заголовок и полезная нагрузка в кодировке base64url, соединенные символом .
.
base64UrlEncode(header) + "."
+ base64UrlEncode(payload)
Это вход для подписания
Хеширование
Затем мы хэшируем входные данные для подписи с помощью алгоритма хэширования SHA-256. Хеширование преобразует одно значение в другое. Хэш-функция использует математический алгоритм для генерации нового значения из существующего.
Примечание:
- Хеширование необратимо. После хеширования входных данных мы не можем вернуться к исходным данным.
- Хеширование всегда дает один и тот же результат для одного и того же входа.
- Никакие два разных ввода хэширования не дадут одинакового результата.
SHA-256 (
base64UrlEncode(header) + "."
+ base64UrlEncode(payload)
)
На этом этапе у нас есть хэш заголовка и сегментов полезной нагрузки, который мы можем сравнить с другими хэшами, но не можем отменить, чтобы вернуться к исходному входу для подписи.
Шифрование
Далее мы шифруем хэшированный входной сигнал для подписи. В отличие от хэширования, шифрование является обратимым. Сервер авторизации шифрует хэшированный входной сигнал подписи с помощью закрытого ключа шифрования, чтобы получить конечный результат.
Этот конечный результат (хэшированный, зашифрованный, закодированный заголовок и полезная нагрузка) является сегментом крипто/подписи — JWT.
RSA (
SHA-256 (
base64UrlEncode(header) + "."
+ base64UrlEncode(payload)
),
{RSA Private Key}
)
Вот и все. Вот как генерируется подпись JSON Web Token.
Процесс валидации
Теперь, когда мы поняли, как был подписан токен, мы можем продолжить и понять, как тот, кто получил токен, может проверить, что этот JWT содержит данные, которые не были подделаны.
Возьмем приложение, которое получило JWT и нуждается в его проверке. Приложение также имеет доступ к открытому ключу сервера авторизации. Валидация JWT — это достижение точки, где мы можем эффективно сравнить то, что мы получили, с тем, что мы ожидаем.
Декодирование утверждений
Приложение может декодировать заголовок и полезную нагрузку, чтобы получить некоторую информацию. Напомним, что эти два сегмента закодированы в base64Url, чтобы сделать их безопасными для URL. В этих сегментах нет ничего криптографически безопасного. Вы можете сделать это с помощью простого онлайн-инструмента декодирования base64. Как только они декодированы, мы можем легко прочитать содержащуюся в них информацию. Например, мы можем декодировать сегмент заголовка, чтобы узнать, каким алгоритмом, по словам JWT, он был подписан.
Из декодированного заголовка мы можем увидеть:
{
"alg": "RS256",
"typ": "JWT"
}
Когда мы читаем алгоритм в заголовке JWT, мы должны убедиться, что он соответствует нашим ожиданиям. Если он не соответствует, мы должны сразу же отклонить токен.
Хеширование (снова)
Если алгоритм в токене соответствует нашему ожиданию RS256, мы знаем, что нам нужно сгенерировать хэш SHA-256 для заголовка и сегментов полезной нагрузки. Обратите внимание, что хэширование необратимо, но один и тот же вход всегда будет давать один и тот же выход. Поэтому мы будем хэшировать скомпонованные, закодированные в base64Url заголовок и полезную нагрузку. Теперь у нас есть входной хэш подписи, свежевычисленный на стороне приложения.
Расшифровка
Хешированный вход подписи также находится в подписи JWT, но он был зашифрован сервером авторизации с помощью закрытого ключа. Приложение имеет доступ к открытому ключу, поэтому мы можем расшифровать подпись. Как только это будет сделано, мы получим доступ к оригинальному хэшу: тому, который был сгенерирован сервером авторизации при первом создании маркера.
Сравнение хэшей
Теперь мы можем сравнить расшифрованный хэш с вычисленным хэшем. Если они совпадают, то мы убедились, что данные в заголовке JWT и сегментах полезной нагрузки не были изменены между моментом создания токена сервером авторизации и моментом его получения нашим приложением.
Проверка утверждений токена
Кроме того, после проверки подписи мы можем проверить данные JSON Web Token. Утверждения в сегменте полезной нагрузки также могут быть проверены, поскольку они содержат информацию об эмитенте токена, сроке действия токена, целевой аудитории токена, информацию, связывающую токен с запросом авторизации, и многое другое.
Эти утверждения предоставляют приложению подробную информацию о токене, которую не может предоставить только проверка подписи. Например, изучение утверждений может показать, что технически действительный токен на самом деле предназначался для другого приложения или пользователя, срок его действия истек, он был получен от эмитента, с которым приложение не связано, и т.д.
Заключение
Мы рассмотрели подписание JWT и проверку подписей JWT. Надеюсь, это поможет вам лучше понять JWT и работать с ними. Я хотел бы повторить, что вы не должны подписывать и проверять токены самостоятельно.
Существуют платформы идентификации, такие как Auth0, Okta, Ping Identity и другие, которые делают все это за вас. Они также предоставляют SDK и библиотеки для валидации и управления токенами на стороне приложения или API. Если вы заинтересованы в защите своих приложений с помощью Auth0, вам нужна учетная запись Auth0. Если у вас его нет, вы можете зарегистрироваться бесплатно.
Спасибо за прочтение! Я очень надеюсь, что вы нашли эту статью полезной. Приглашаю вас принять участие в обсуждении в комментариях ниже, мне всегда интересно узнать ваши мысли и я рад ответить на любые вопросы, которые могут возникнуть у вас в голове. Если вы считаете, что эта статья была полезной, пожалуйста, поставьте лайк, чтобы помочь продвинуть эту статью для других.
Спасибо, что читаете! 🙂
P.S Не стесняйтесь общаться со мной в LinkedIn или Twitter.
Приложение
Следующие материалы помогли мне написать эту статью:
- Подписание и проверка подлинности JSON Web Tokens (JWT) для всех от Kim Maida
- Обзор алгоритмов подписания JSON Web Token (JWT) от Auth0