Недавно меня попросили написать приложение React / Redux и использовать Azure Active Directory для его служб идентификации. При запуске нового приложения ASP.NET Core в Visual Studio вы обнаружите, что в шаблон не встроена аутентификация. Конечно, это возможно, но для поддержки этого приложения потребуются изменения.

Это приводит к нашему следующему логическому вопросу: какую библиотеку я могу использовать для поддержки этого? Начав поиск в Интернете, вы обнаружите, что на самом деле существует две конечные точки Azure AD: v1 и v2. В зависимости от вашего решения вам нужно будет настроить таргетинг на другую библиотеку. V1 использует ADAL.js, а v2 использует MSAL.js.

Исходя из требований проекта, над которым я работал, я решил, что буду использовать библиотеку v1 ADAL.js. В своей первой попытке реализовать это я начал использовать эту библиотеку и писать собственные оболочки React для реализации. Потом меня осенило, я уверен, что кто-то делал это раньше. Итак, я переключил передачу, нашел пакет response-adal npm и интегрировал его в свое решение. Первоначальная интеграция с решением работала; однако ему не хватало интеграции с Redux, и я снова начал писать свой собственный код Redux для обработки обработки.

Примерно на полпути я понял, что меня тоже не устраивает эта реализация, и начал искать лучшее решение. Введите redux-oidc. OAuth 2.0 - это стандартный протокол, на основе которого был построен OpenID Connect. Azure Active Directory - это облачный поставщик услуг идентификации, который предоставляет конечные точки OpenId Connect и OAuth 2.0. Это означает, что мы можем использовать более стандартную библиотеку, которая правильно реализует спецификации протокола в наших приложениях.

Образец заявки

Чтобы продемонстрировать это поведение, я решил использовать готовый шаблон Visual Studio в качестве начального приложения и интегрировать Azure Active Directory с помощью redux-oidc и oidc-client. По мере продвижения будет полезно создать новый проект, используя шаблон Redux ASP.NET Core React в качестве отправной точки. Цель этой статьи - помочь вам понять, что нужно изменить в вашем приложении, чтобы это работало. Отдельно отметим, что мы защитим веб-API, чтобы разрешить доступ только авторизованным пользователям.

Если вам нужен ярлык для этой реализации, не стесняйтесь просмотреть код здесь, на GitHub:

Вот шаги, необходимые для работы:

  1. Настройка Azure Active Directory
  2. Добавить зависимости npm
  3. Настройте свой userManager
  4. Настройте свой Redux Store
  5. Интегрируйте OidcProvider в свое приложение
  6. Создать страницу обратного вызова
  7. Реализовать вход / выход
  8. Зарегистрировать маршруты и изменить навигацию
  9. Реализуйте частные маршруты
  10. Защитите свой API

Настройка Azure Active Directory

Чтобы правильно настроить это приложение, у вас должно быть несколько ресурсов в Azure. Вам понадобится клиент Azure Active Directory и две регистрации приложений Azure: регистрация клиентского приложения и регистрация приложения через API. Пожалуйста, просмотрите файл прочтите меня на прилагаемом GitHub, чтобы узнать, как это сделать.

Добавить зависимости npm

Как упоминалось во введении, нам нужно добавить в наше приложение redux-oidc и oidc-client. Пожалуйста, выполните следующие команды на терминале:

npm install redux-oidc oidc-client

Настроить UserManager

При настройке хранилища Redux мы включаем экземпляр класса UserManager, который содержит основную конфигурацию для нашей авторизации.

Создайте новый файл Javascript с именем userManager.js в папке ClientApp \ src \ util.

При добавлении этого класса вам нужно будет добавить несколько различных значений конфигурации, специфичных для вашего приложения. Они есть:

  1. Идентификатор клиента - это идентификатор зарегистрированного приложения пользовательского интерфейса, зарегистрированного в Azure Active Directory.
  2. Идентификатор клиента - также называется идентификатором каталога вашего домена Azure Active Directory.
  3. Идентификатор ресурса - это идентификатор зарегистрированного приложения API, которое вы зарегистрировали в своем приложении.
  4. Ключи подписи - из-за исключения CORS при локальном запуске этого приложения вам необходимо явно указать ключи подписи. У вас есть несколько вариантов, но с целью демонстрации вы переходите на страницу ключей, найденную в Azure, и копируете и вставляете ключи значений в этот массив.

Если у вас возникнут трудности с поиском любого из этих значений, обратитесь к разделу Прочтите меня в прилагаемом репозитории GitHub.

Настройте свой магазин Redux

Чтобы настроить магазин Redux, вам необходимо сделать следующее:

  1. Импортируйте и добавьте oidcReducer в список редюсеров.
  2. Выполните loadUser из redux-oidc и передайте его вашему магазину вместе с вашим менеджером пользователей.

Внесите в файл configureStore.js следующие изменения:

Интегрируйте OidcProvider в наше приложение

Этот компонент настраивает обработчики событий userManager для отправки необходимых действий.

Для этого измените index.js приложения следующим образом:

Создать страницу обратного вызова

После завершения аутентификации пользователь вернется по указанному вами URL. Строка запроса содержит параметры, которые должны быть обработаны вашим приложением для завершения цикла аутентификации. Redux-oidc CallbackComponent выполняет большую часть тяжелой работы по интеграции с Redux. После этого пользователь перенаправляется на домашнюю страницу.

Создайте новый файл с именем CallbackPage.js и вставьте следующий код:

Реализовать страницы входа / выхода

Чтобы активировать функции входа и выхода на сайте, мы создаем на нашем сайте две страницы: LoginPage.js и LogoutPage.js.

На странице входа есть простая кнопка, которая использует UserManager для запуска процесса входа. Пользователь перенаправляется на страницу входа в Azure и по завершении возвращается на страницу обратного вызова в нашем приложении.

Страница выхода просто перенаправляет пользователя на страницу выхода в Azure при загрузке.

Зарегистрировать маршруты и изменить навигацию

Чтобы наше приложение отвечало на созданные страницы, давайте изменим маршруты приложения:

Теперь давайте изменим нашу навигацию по сайту, чтобы добавить ссылки входа / выхода, когда это необходимо, и сделать так, чтобы они отражали наше имя пользователя, когда мы вошли в систему:

Теперь мы сопоставляем объект oidc в функции mapStateToProps, а затем используем его, чтобы определить, вошли ли мы в систему. Если мы вошли в систему, мы отобразим уникальное имя из нашего идентификационного токена, хранящегося в хранилище redux. Кроме того, мы переключаем ссылки входа / выхода в зависимости от этого статуса.

Реализуйте частные маршруты

Чтобы автоматически требовать от пользователя входа в систему при доступе к определенным маршрутам, давайте создадим общий компонент для обработки этого. Создайте новый файл ClientApp \ src \ components \ common \ PrivateRoute.js и следующий код:

Когда этот компонент загружается, он загружает объект oidc из состояния Redux. Затем во время рендеринга он проверяет, есть ли внутри допустимый пользовательский объект. Если пользователь не найден, вместо него отображается страница входа.

Защитите свой API

На этом этапе наше клиентское приложение настроено для правильного входа и выхода пользователя с помощью Azure Active Directory, отражения имени пользователя, вошедшего в систему, в меню и для доступа к определенным маршрутам. Однако это не защищает данные на нашем сервере. Теперь давайте защитим наш API и потребуем авторизации пользователя для доступа к нему.

Для этого необходимо несколько модификаций:

  1. Добавьте аутентификацию в наши методы ConfigureServices и Configure
  2. Добавить конфигурацию Azure AD
  3. Украсьте наш API атрибутом авторизации
  4. Измените наши вызовы API на стороне клиента, чтобы включить токен-носитель

1. Добавить аутентификацию

Создайте два вспомогательных метода расширения для папки с именем Extensions:

AzureAdAuthenticationBuilderExtensions.cs - этот класс помогает нам настроить наше приложение, а также обеспечивает обработку службы Jwt Bearer.

AzureAdOptions.cs - значения конфигурации, которые мы включаем в наш файл appSettings.json.

Как только эти значения будут здесь, нам нужно обновить наш класс Startup.cs, чтобы использовать наши вспомогательные методы и включить аутентификацию.

2. Добавьте конфигурацию Azure AD.

Теперь нам нужно изменить файл appsettings.json с нашими новыми настройками Azure AD:

Обратите внимание, что вам нужно будет обновить домен, TentantId и Client ID значениями из Azure.

  • Домен. Если вы выполнили настройку в файле «прочтите меня» на github, это должно быть что-то вроде {ваш домен} .onmicrosoft.com.
  • Идентификатор клиента - также называется идентификатором каталога вашего домена Azure Active Directory.
  • ClientID - это идентификатор приложения вашего API. Клиент назвал это идентификатором ресурса.

3. Украсьте наш API атрибутом авторизации.

Теперь мы можем украсить наши контроллеры API атрибутом авторизации. Если пользователь не вошел в систему, он получит ответ 401 неавторизованный.

4. Измените наши вызовы клиентского API, включив в него токен-носитель.

Наконец, нашему клиентскому приложению теперь необходимо отправить токен аутентификации в заголовках авторизации HTTP в форме токена-носителя. Для этого измените литерал объекта WeatherForecast.js actionCreators следующим образом:

Этот метод деструктурирует объект oidc из состояния нашего приложения redux. Затем он присоединяет сохраненный access_token в качестве токена-носителя к запросу. Когда API получает этот токен, он проверяет его и, по сути, регистрирует пользователя в API и авторизует его.

Использованная литература: