Почему Auth0?
Платформа Auth0 представляет собой онлайн сервис для аутентификации и авторизации и включает в себя управление пользователями, проверку их идентификационных данных, управление токенами и сессией. На стороне клиента данного сервиса необходимо осуществить обращение к уникальному URI и после аутентификации использовать полученные при обратном редиректе токены и кукис. Всю логику проверки данных пользователя, сохранения сессии и токенов берет на себя Auth0. После успешной аутентификации пользователя сервис Auth0 осуществляет редирект обратно на адрес своего клиента.
Auth0 предоставляет удобные UI компоненты для получения идентификационных данных - виджеты для входа, регистрации, восстановления пароля. Данные виджеты включают также возможности логина с помощью сторонних сервисов - вход через аккаунт Google, Microsoft, GitHub и многие другие.
Виджет интуитивен и удобен в использовании. Он уже стал стандартом и, можно сказать, лицом технологии Single Sign-On.
Уникальный логин с помощью Customize Login Page
Виджет легко настраивается как в плане добавления контролов: какие элементы добавить, а какие скрыть, так и в плане визуальном: шрифт, цвет текста, кнопок, фона, фокуса, кастомные лого и приветствие.
Однако, иногда не хватает возможностей даже такого гибкого инструмента. В частности, иногда необходимо осуществить предварительную валидацию до того, как запрашивать аутентификационный сервис, или требуется реализовать отличающуюся логику входа для разных видов пользователей, в том числе с перенаправлением на разные сервисы. Тем не менее, при этом необходимо сохранить для пользователя ту же визуальную картинку или следовать особым требованиям дизайнера.
Для данных случаев у Auth0 имеется решение - Customize Login Page. В данном разделе настроек своей аппликации в Auth0 вы можете определить html страницу, которая будет показана вместо виджета Auth0 на его уникальном для вас адресе. Auth0 предоставляет два базовых шаблона, содержащих html теги элементов и соответствующий js скрипт для них. Этого достаточно, чтобы принять данные от пользователя, отправить запрос на аутентификацию и при положительном ответе осуществить редирект обратно на вашу аппликацию.
Для нашей команды данное решение показалось неприемлемым с точки зрения необходимости вмешиваться в статический html каждый раз, когда мы меняем какие-то элементы или логику.
В связи с этим, мы решили разработать небольшую аппликацию для страницы логина, осуществлять ее поддержку у нас в команде локально, а в настройках Auth0 определить только линк на скрипт, который будет поднимать нашу аппликацию и управлять ею, то есть динамически отрисовывать тот контент, который мы можем менять по своему усмотрению.
Как настроить кастомизированный логин?
О том, как настроить админку в Auth0 предлагаю почитать вот здесь: React: пример использования Auth0 для разработки сервиса аутентификации/авторизации.
Рабочий образец можно посмотреть вот здесь: https://github.com/IvanovaNataly/auth-custom-login
Проект построен на react с помощью vite и mui, то есть его первые пакеты загружаем так:
npm create vite@latest
npm i @mui/material
В админке Auth0 переходим на вкладку Branding, затем на Universal Login, находим Advanced Options и далее вкладку Login. На этой странице активируем тогл Customize Login Page и добавляем следующий html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script>
var config = encodeURIComponent(window.atob('@configg@@'));
</script>
<script src="https://[your_domain]/dist/assets/index.js"></script>
</body>
</html>
Это та страница, которая будет отрисована при переходе на уникальный URI для аутентификации в рамках Auth0. Она содержит в себе:
корневой элемент, на котором наша реактовская аппликация построит страницу.
скрипт с плейсхолдером <@configg@@>. В момент поднятия страницы сервис Auth0 заменяет этот плейсхолдер на объект, содержащий все параметры, необходимые для запроса об аутентификации и последующего формирования токенов и кукис. Впоследствии мы воспользуемся этим объектом уже на нашей поднятой странице.
ссылку на скрипт, который по существу и является нашей скомпилированной аппликацией. Ссылка остается постоянной, содержание скрипта может изменяться в процессе разработки;‑)
Внутри нашего реактовского проекта основной рабочей компонентой является LoginForm. Она содержит в себе:
форму — компонент Box (mui), который рендерится как тэг <form> и запускает метод handleSubmit.
два текстовых поля ввода — компоненты TextField (mui), которые запускают методы handleChange & handleBlur, а также показывают ошибки.
кнопку — компонент Button (mui), которая неактивна до тех пор, пока не будет пройдена первичная валидация на стороне клиента.
При вводе имени и пароля в соответствующие поля формы с помощью методов handleChange, handleBlur, handleError осуществляется первичная валидация. При получении допустимых значений кнопка становится активной, и тогда с помощью метода requestLogin можно послать запрос на аутентификацию на сервер.
Параметры данного запроса формируются с помощью библиотеки auth0-js, поэтому добавляем ее в проект:
npm i auth-js
При запуске компоненты она обращается к объекту config, который мы получили в первом тэге <script> нашего статического html документа.
Далее проводим декодировку объекта:
const config = JSON.parse(decodeURIComponent(window.config));
Формируем параметры нашего локального инстанса auth0:
const params = Object.assign({
overrides: {
__tenant: config.auth0Tenant,
__token_issuer: config.authorizationServer.issuer
},
domain: config.auth0Domain,
clientID: config.clientID,
redirectUri: config.callbackURL,
responseType: 'code'
}, config.internalOptions);
И далее запускаем его:
const webAuth = new auth0.WebAuth(params);
При отправке формы на сервер метод requestLogin обращается к локальному инстансу auth0, вызывает его метод login с аргументами в виде способа авторизации (realm) и данных пользователя (username & password).
В случае, если авторизация не прошла успешно (невалидные данные пользователя), обрабатываем ошибку, таким же образом как и ошибки первичной валидации, с помощью метода handleError. Это позволяет нам показать пользователю описание ошибки, полученное с сервера, и подсветить поля красным.
В случае, если авторизация прошла успешно, осуществляется переадреcация на адрес, указанный в вашей админке Auth0 как callbackURL. Логично предположить, что это будет адрес, с которого первоначально вызывался сервис Auth0.
Вуаля, авторизация пользователя завершена, он может успешно разлогиниться и отдохнуть )))
Прим.: для того, чтобы запустить проект, выложенный здесь, нужно зарегистрироваться на Auth0, прописать в админке все необходимые настройки и добавить маленькую статическую страничку, которая приведена выше, с правильным путем к скомпилированному файлу js. В самом проекте никаких настроек и параметров прописывать не надо.
Прим.прим.: в проекте для стилей использована библиотека @emotion, с которой по умолчанию работает mui. Однако в отдельной ветке feature/css есть вариант с простым css. В случае использования его, нужно в статической странице после ссылки на скрипт js, добавить линк на скомпилированный файл css.