Введение

Тестирование аутентификации в вашем приложении имеет решающее значение. При интеграции с 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 г.