Добавление входа с помощью Azure Active Directory B2C в веб-приложение Spring

В этой статье показано, как создать приложение Java с возможностью входа с помощью Spring Initializr с идентификатором Spring Boot Starter для Microsoft Entra ID.

В этом руководстве описано следующее:

  • создание приложения Java с помощью Spring Initializr;
  • настройка Azure Active Directory B2C;
  • защита приложения с помощью классов и аннотаций Spring Boot;
  • сборка и тестирование приложения Java.

Идентификатор Microsoft Entra — это облачное решение корпоративного удостоверения Майкрософт. Azure Active Directory B2C комплиментирует набор функций идентификатора Microsoft Entra, позволяя управлять доступом клиентов, потребителей и граждан к приложениям B2C.

Необходимые компоненты

Внимание

Для выполнения действий, описанных в этой статье, требуется spring Boot версии 2.5 или более поздней.

Создание приложения с помощью Spring Initializr

  1. Перейдите в https://start.spring.io/.

  2. Укажите значения в соответствии с инструкциями в этом руководстве. Метки и макет могут отличаться от изображения, показанного здесь.

    • В поле Project (Проект) выберите элемент Maven Project (Проект Maven).
    • В поле Language (Язык) выберите элемент Java.
    • В разделе Spring Boot выберите 2.7.11.
    • В полях Group (Группа), Artifact (Артефакт) и Name (Имя) введите одно и то же строковое значение с кратким описанием проекта. Пользовательский интерфейс может автоматически заполнить некоторые из этих полей при вводе.
    • На панели Dependencies (Зависимости) выберите элемент Add Dependencies (Добавить зависимости). Через предоставленный пользовательский интерфейс добавьте зависимости Spring Web и Spring Security.

    Примечание.

    Выпущены версии Spring Security 5.5.1, 5.4.7, 5.3.10 и 5.2.11, чтобы решить проблему, описанную в отчете об уязвимостях (CVE) CVE-2021-22119: атака типа "отказ в обслуживании" с использованием spring-security-oauth2-client. Если вы используете более раннюю версию, обновите ее.

  3. Щелкните элемент Generate Project (Создать проект), затем скачайте проект в папку на локальном компьютере. Переместите скачанный файл в каталог, имя которого совпадает с именем проекта, и распакуйте этот файл. Макет файла должен быть похож на представленный ниже пример, но с указанным вами значением для параметра Group (Группа) вместо указанного здесь yourProject.

    .
    ├── HELP.md
    ├── mvnw
    ├── mvnw.cmd
    ├── pom.xml
    └── src
        ├── main
        │   ├── java
        │   │   └── yourProject
        │   │       └── yourProject
        │   │           └── YourProjectApplication.java
        │   └── resources
        │       ├── application.properties
        │       ├── static
        │       └── templates
        └── test
            └── java
                └── yourProject
                    └── yourProject
                        └── YourProjectApplicationTests.java
    

Создание и инициализация экземпляра Microsoft Entra

Создание экземпляра Active Directory

  1. Войдите на сайт https://portal.azure.com.

  2. Выберите Создать ресурс. Выполните поиск по фразе Azure Active Directory B2C.

    Создайте новый экземпляр Azure Active Directory B2C с помощью портала Azure.

  3. Нажмите кнопку создания.

    Запись Azure Marketplace для Azure Active Directory B2C.

  4. Выберите Создать новый клиент Azure AD B2C.

    Элементы управления на портале Azure для создания арендатора Azure AD B2C.

  5. Введите подходящие значения в полях Имя организации и Первоначальное доменное имя, а затем щелкните элемент Создать.

    Экран создания арендатора Azure AD B2C.

  6. После завершения создания Active Directory выберите учетную запись в правом верхнем углу, выберите каталог Switch, а затем выберите созданный каталог. Вы будете перенаправлены на домашнюю страницу нового клиента. Выполните поиск по строке b2c и выберите Azure AD B2C.

    Поиск службы Azure AD B2C.

Регистрация приложения для приложения Spring Boot

  1. В области "Управление" выберите Регистрация приложений и выберите "Создать регистрацию".

    Снимок экрана: портал Azure с окном

  2. В поле Имя введите имя своего приложения и щелкните Зарегистрировать.

    Форма регистрации приложения Azure AD B2C.

  3. Вернитесь в область Управление, щелкните Регистрации приложений, а затем выберите имя созданного приложения.

    Экран регистрации приложений, где выбрано отображаемое имя.

  4. Щелкните Проверка подлинности, Добавить платформу и Интернет. В поле URI перенаправления задайте значение http://localhost:8080/login/oauth2/code/ и щелкните Настроить.

    Элементы управления для выбора проверки подлинности, добавления платформы и Интернета.

    Экран настройки, где выбрано поле

Добавление секретов в приложение

Выберите Сертификаты и секреты и Новые секреты клиента. Введите описание нового секрета и щелкните Добавить. После создания секрета щелкните значок копирования рядом со значением этого секрета, чтобы сохранить это значение для дальнейшего использования.

Экран добавления секрета клиента.

Экран

Примечание.

Если вы оставьте раздел "Сертификаты" и "Секреты " и вернетесь, вы не сможете увидеть значение секрета. В таком случае вам нужно будет создать еще один секрет и скопировать его для дальнейшего использования. Иногда созданное значение секрета может содержать символы, которые сложно включить в файл application.yml, например обратную косую черту или обратный апостроф. В этом случае просто удалите такой секрет и создайте новый.

Добавление потока пользователя

  1. Откройте главную страницу клиента. В разделе Политики на панели слева выберите элемент Потоки пользователя, а затем команду Создать поток пользователя.

  2. Теперь вы покинете это руководство, выполните другое руководство и вернетесь к этому руководству, когда закончите работу. При переходе к другому руководству следует помнить о некоторых вещах.

    • Начните с этапа, на котором предлагается выбрать действие Создать поток пользователя.
    • При каждом упоминании webapp1 в этом руководстве заменяйте его тем значением, которое вы указали в поле Group (Группа).
    • При выборе утверждений для возврата из потоков убедитесь, что выбрано отображаемое имя . Без этого утверждения приложение, созданное в этом руководстве, не будет работать.
    • Когда вам будет предложено запустить потоки пользователей, url-адрес перенаправления, указанный ранее, еще не активен. Вы по-прежнему можете запускать потоки, но перенаправление не завершится успешно. Это ожидаемо.
    • Когда вы дойдете до этапа "Дальнейшие действия", вернитесь к этому руководству.

    Выполните все действия, описанные в руководстве. Создание потоков пользователей в Azure Active Directory B2C для создания потоков пользователей для регистрации и входа в систему, редактирования профиля и сброса пароля.

    Azure AD B2C поддерживает локальные учетные записи, а также поставщики удостоверений социальных сетей. Пример создания поставщика удостоверений GitHub см. в статье Настройка регистрации и входа с учетной записью GitHub через Azure Active Directory B2C.

Настройка и компиляция приложения

Итак, вы создали экземпляр Azure AD B2C и несколько потоков пользователей, которые позволят вам подключить приложение Spring к этому экземпляру Azure AD B2C.

  1. В сеансе командной строки перейдите с помощью команды cd в каталог, куда вы распаковали содержимое ZIP-файла, скачанного из Spring Initializr.

  2. Перейдите в родительскую папку проекта и откройте файл проекта Maven pom.xml в текстовом редакторе.

  3. Добавьте в pom.xml зависимости для применения защиты Spring OAuth2:

    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory-b2c</artifactId>
        <version>See Below</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
        <version>See Below</version>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        <version>See Below</version>
    </dependency>
    

    Для параметра spring-cloud-azure-starter-active-directory-b2c укажите последнюю доступную версию. Вы можете найти ее на сайте mvnrepository.com.

    Для параметра spring-boot-starter-thymeleaf укажите версию, которая соответствует выбранной версии Spring Boot, например 2.3.4.RELEASE.

    Для параметра thymeleaf-extras-springsecurity5 укажите последнюю доступную версию. Вы можете найти ее на сайте mvnrepository.com. На момент написания этой статьи последняя версия имела номер 3.0.4.RELEASE.

  4. Сохраните и закройте файл pom.xml.

    • Проверьте правильность всех зависимостей, выполнив mvn -DskipTests clean install. Если вы не видите BUILD SUCCESS, устраните и устраните проблему, прежде чем продолжить.
  5. Перейдите к папке src/main/resources проекта и создайте файл application.yml в текстовом редакторе.

  6. Задайте параметры для регистрации вашего приложения, используя созданные ранее значения. Например:

    spring:
      cloud:
        azure:
          active-directory:
            b2c:
              enabled: true
              base-uri: https://<your-tenant-initial-domain-name>.b2clogin.com/<your-tenant-initial-domain-name>.onmicrosoft.com/
              credential:
                client-id: <your-application-ID>
                client-secret: '<secret-value>'
              login-flow: sign-up-or-sign-in
              logout-success-url: <your-logout-success-URL>
              user-flows:
                sign-up-or-sign-in: <your-sign-up-or-sign-in-user-flow-name> 
                profile-edit: <your-profile-edit-user-flow-name> 
                password-reset: <your-password-reset-user-flow-name> 
              user-name-attribute-name: <your-user-name-attribute-name> 
    

    Обратите внимание, что значение client-secret заключено в одинарные кавычки. Это необходимо потому, что значение <secret-value> почти наверняка будет содержать некоторые символы, которые в формате YAML обязательно заключаются в одинарные кавычки.

    Примечание.

    На момент написания этой статьи для интеграции Active Directory B2C со Spring в файле application.yml можно указывать следующие значения:

    spring:
      cloud:
        azure:
          active-directory:
            b2c:
              enabled: true
              base-uri:
              credential:
                client-id:
                client-secret:
              login-flow:  
              logout-success-url:
              user-flows:
                sign-up-or-sign-in:
                profile-edit: # optional
                password-reset: # optional
              user-name-attribute-name:
    

    Файл application.yml доступен в примере spring-cloud-azure-starter-active-directory-b2c: aad-b2c-web-application на GitHub.

  7. Сохраните и закройте файл application.yml.

  8. Создайте папку с именем контроллера в src/main/java/<yourGroupId>/<yourGroupId>, заменив <yourGroupId> введенным значением для группы.

  9. Создайте файл Java с именем WebController.java в папке controller и откройте его в текстовом редакторе.

  10. Введите в файл следующий код, изменив yourGroupId соответствующим образом, а затем сохраните и закройте файл:

    package yourGroupId.yourGroupId.controller;
    
    import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
    import org.springframework.security.oauth2.core.user.OAuth2User;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    public class WebController {
    
        private void initializeModel(Model model, OAuth2AuthenticationToken token) {
            if (token != null) {
                final OAuth2User user = token.getPrincipal();
    
                model.addAttribute("grant_type", user.getAuthorities());
                model.addAllAttributes(user.getAttributes());
            }
        }
    
        @GetMapping(value = "/")
        public String index(Model model, OAuth2AuthenticationToken token) {
            initializeModel(model, token);
    
            return "home";
        }
    
        @GetMapping(value = "/greeting")
        public String greeting(Model model, OAuth2AuthenticationToken token) {
            initializeModel(model, token);
    
            return "greeting";
        }
    
        @GetMapping(value = "/home")
        public String home(Model model, OAuth2AuthenticationToken token) {
            initializeModel(model, token);
    
            return "home";
        }
    }
    

    Так как каждый метод в контроллере вызывает initializeModel(), а этот метод вызывает model.addAllAttributes(user.getAttributes());, любая HTML-страница в src/main/resources/templates может получить доступ к любому из этих атрибутов, таким как ${name}, ${grant_type}или ${auth_time}. Значения, возвращаемые из user.getAttributes(), фактически являются утверждениями id_token для проверки подлинности. Полный список доступных утверждений приведен в статье Маркеры идентификаторов платформы удостоверений Майкрософт.

  11. Создайте папку с именем безопасности в src/main/java/<yourGroupId>/<yourGroupId>, заменив yourGroupId введенным значением для группы.

  12. Создайте файл Java с именем WebSecurityConfiguration.java в папке security и откройте его в текстовом редакторе.

  13. Введите в файл следующий код, изменив yourGroupId соответствующим образом, а затем сохраните и закройте файл:

    package yourGroupId.yourGroupId.security;
    
    import com.azure.spring.cloud.autoconfigure.aadb2c.AadB2cOidcLoginConfigurer;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    @EnableWebSecurity
    public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        private final AadB2cOidcLoginConfigurer configurer;
    
        public WebSecurityConfiguration(AadB2cOidcLoginConfigurer configurer) {
            this.configurer = configurer;
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                    .anyRequest()
                    .authenticated()
                    .and()
                    .apply(configurer)
            ;
        }
    }
    
  14. Скопируйте файл home.html из примера spring-cloud-azure-starter-active-directory-b2c: aad-b2c-web-application в src/main/resources/templates, а также замените ${your-profile-edit-user-flow}${your-password-reset-user-flow} имена созданных ранее потоков пользователей.

Создание и тестирование приложения

  1. Откройте командную строку и перейдите из каталога в папку с файлом pom.xml.

  2. Создайте приложение Spring Boot с помощью Maven и запустите его, например, следующим образом:

    Примечание.

    Очень важно, чтобы время системных часов на том устройстве, где выполняется локальное приложение Spring Boot, было точным. При использовании OAuth 2.0 допускается лишь очень малое отклонение по времени. Даже три минуты неточности могут привести к появлению при входе ошибок следующего вида: [invalid_id_token] An error occurred while attempting to decode the Jwt: Jwt used before 2020-05-19T18:52:10Z. На момент написания этой статьи сайт time.gov предоставлял информацию о том, насколько показания ваших часов отличаются от реального времени. Приложение успешно выполнено с отклонением в +0,019 секунд.

    mvn -DskipTests clean package
    mvn -DskipTests spring-boot:run
    
  3. Скомпилировав и запустив приложение с помощью Maven, перейдите в веб-браузере по адресу http://localhost:8080/, после чего вы будете перенаправлены на страницу входа.

    Страница входа в веб-приложение.

  4. Выберите ссылку с текстом, обозначающим процесс входа. Вы перейдете на страницу Azure AD B2C, где можете начать проверку подлинности.

  5. После успешного входа в систему вы увидите пример home page из браузера.

    Успешный вход в веб-приложение.

Устранение неполадок

В следующих разделах описано, как устранить некоторые проблемы, с которыми вы можете столкнуться.

Отсутствует имя атрибута

При выполнении этого примера вы можете получить исключение с сообщением Missing attribute 'name' in attributes. В журнале для этого исключения будет сохранена примерно такая информация:

java.lang.IllegalArgumentException: Missing attribute 'name' in attributes
at org.springframework.security.oauth2.core.user.DefaultOAuth2User.<init>(DefaultOAuth2User.java:67) ~[spring-security-oauth2-core-5.3.6.RELEASE.jar:5.3.6.RELEASE]
at org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser.<init>(DefaultOidcUser.java:89) ~[spring-security-oauth2-core-5.3.6.RELEASE.jar:5.3.6.RELEASE]
at org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService.loadUser(OidcUserService.java:144) ~[spring-security-oauth2-client-5.3.6.RELEASE.jar:5.3.6.RELEASE]
at org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService.loadUser(OidcUserService.java:63) ~[spring-security-oauth2-client-5.3.6.RELEASE.jar:5.3.6.RELEASE]

Если вы увидите такую ошибку, проверьте правильность рабочего процесса, который вы создали, как описано в статье Руководство. Создание потоков пользователей в Azure Active Directory B2C. При создании рабочего процесса в разделе Атрибуты пользователя и утверждения обязательно выберите атрибуты и утверждения для элемента Отображаемое имя. Также обязательно правильно настройте user-name-attribute-name в файле application.yml.

Зацикливание процесса входа на конечную точку B2C

Такая проблема чаще всего связана с испорченными файлами cookie для localhost. Очистите файлы cookie для localhost и повторите попытку.

Итоги

В рамках этого руководства вы создали веб-приложение Java с использованием начального приложения Spring для Azure Active Directory B2C, настроили клиент Azure AD B2C, зарегистрировали в нем созданное приложение, а затем настроили это приложение для использования аннотаций и классов Spring для защиты веб-приложения.

Очистка ресурсов

Если они больше не нужны, используйте портал Azure, чтобы удалить ресурсы, созданные в этой статье во избежание непредвиденных расходов.

Следующие шаги

Дополнительные сведения о Spring и Azure см. в центре документации об использовании Spring в Azure.