Введение
Тестирование аутентификации в вашем приложении имеет решающее значение. При интеграции с Auth0 становится сложнее. Вы не можете генерировать нужные токены. Для их API используется ограничение скорости. Это также не то, о чем они должны беспокоиться. Ваша реализация должна быть обработана вами.
Чтобы модульное тестирование было быстрым, мы должны иметь возможность быстро запускать действительные токены, недействительные токены, токены с истекшим сроком действия и т. д., чтобы проверить наш уровень аутентификации. Одной из удобных библиотек для этого является mock-jwks.
Это будет имитировать вызовы хорошо известной конечной точки JWK, а также управлять подписанием и генерацией токенов для нас. По сути, он будет притворяться Auth0 для нас.
В этом уроке мы также предполагаем использовать babel, чтобы мы могли делать такие вещи, как использование import
.
Узнайте больше о том, почему RS256 и использование JWK лучше, чем просто случайные ключи подписи https://auth0.com/blog/navigating-rs256-and-jwks/
Код для проверки JWT
Сначала давайте настроим код, который проверяет, действителен ли токен. Нам понадобится библиотека jsonwebtoken
и библиотека jwks-rsa
. Оба от Auth0.
Мы импортируем и создадим файл jwksClient
. Затем мы предоставим ему наш URL-адрес для наших приложений JWKS. Это URL-адрес, который будет иметь наши ключи подписи для проверки того, что токен получен из правильного приложения Auth0, но не предоставляет закрытые ключи, позволяющие подписывать новые токены.
У вас может быть что-то в этом роде. Нам нужно, чтобы наш вызов jwt.verify
был асинхронным, так как нам нужно будет загрузить файл JWKS
. Вместо того, чтобы использовать обратные вызовы, мы заключаем их в промис, чтобы мы могли легко работать с async/await.
Мы получаем token
для проверки, обратный вызов getKey
, о котором мы услышим через секунду, а затем предоставляем наш алгоритм и обратный вызов для обработки возвращенной ошибки или декодированного токена.
getKey
— это функция, которую библиотека jsonwebtoken
будет вызывать с заголовком и обратным вызовом, чтобы сообщить ей, что мы потерпели неудачу или успешно загрузили ключ подписи.
Используя нашу библиотеку jwks-rsa
, мы просим ее получить наш ключ подписи для определенного kid
. kid
— это уникальный идентификатор ключа. jwks.json
, который мы загружаем из Auth0, будет иметь соответствующий ключ подписи для нашего kid
. Таким образом, нам нужно kid
, чтобы знать, какой ключ использовать, чтобы проверить, действителен ли наш токен.
Наконец, мы получаем наш публичный ключ подписи и звоним callback
с ключом. Это все здорово, но издеваться над этим или получить настоящие токены может быть непросто.
Настройка среды
Итак, давайте настроим нашу среду jest, чтобы мы могли смоделировать этот поток и проверить нашу аутентификацию.
Сначала нам нужно установить несколько библиотек. Большинство из них связаны с шутками, кроме mock-jwks
и nock
. Nock имитирует HTTP-запросы, а mock-jwks
генерирует наши ключи подписи и токены и использует nock для возврата ответов.
Это наш babel.config.js
.
Настройка шутливых тестов
С установленным jest
мы можем отредактировать наш package.json
, чтобы иметь скрипт для запуска наших тестов. Что-то типа
В каталоге __tests__
мы можем создать тест, соответствующий тому, что будет запускать Jest. В нашем случае мы назвали его auth.test.js
.
Нам нужно инициировать mock-jwks
. Поэтому мы вызываем его с помощью пути нашего приложения Auth0. https://MYAUTH0APP.auth0.com/
. Путь к URL-адресу для jwks
является вторым аргументом для createJWKSMock
, однако по умолчанию он равен well-known/jwks.json
, поэтому нам не нужно ничего там делать.
Перед каждым тестом мы будем запускать наш слушатель jwks-mock
, а также останавливать его после каждого теста.
Написание теста
Теперь давайте посмотрим, что значит написать тест с использованием mock-jwks
. Мы импортировали нашу функцию verifyAuth0Token
. Теперь нам нужно получить токен для проверки.
Созданный нами клиент имеет метод token
, который будет принимать полезную нагрузку данных. Это полезные данные, которые вы обычно записываете в токен при вызове jwt.sign
и создании действительного токена.
У нас нет никаких данных, которые нам нужны, поэтому мы можем просто передать пустой объект и получить действительный токен.
Мы вызываем наш вызов verifyAuth0Token
и ожидаем, что данные, которые мы получим, совпадут. Причина, по которой это работает, заключается в том, что если наш вызов jwt.verify
получит недопустимый токен, он выдаст ошибку.
Таким образом, чтобы проверить выброшенную ошибку в Jest с помощью асинхронного режима, простым способом является использование вызова expect.assertions
и try/catch.
Мы говорим, что ожидаем ровно 1 утверждение. Это утверждение будет в улове. Если бы токен по какой-то причине был действительным, мы бы получили ошибку, потому что catch
никогда не будет запущено, и мы никогда не получим требуемое утверждение 1.
Мы передаем exp: 0
нашему токену. На самом деле не имеет значения, когда истекает срок действия токена, поскольку мы просто проверяем, что он улавливает просроченные токены как недействительные.
В нашем catch
мы можем ожидать, что должны получить ошибку, но мы можем быть еще более конкретными и ожидать TokenExpiredError
.
Вывод
С помощью mock-jwks
мы можем запускать модульные тесты с действительными, недействительными и любыми полезными данными, которые нам нужны, без обращения к серверу. Таким образом, наши тесты остаются быстрыми, поэтому мы можем надлежащим образом проводить модульное тестирование. Кроме того, нам не нужно добавлять какие-либо хаки в наш код, чтобы протестировать его. Мы просто издеваемся над тем, как это будет работать в реальном мире.
Первоначально опубликовано на https://codedaily.io 29 февраля 2020 г.