Spring 웹앱에 Azure Active Directory B2C로 로그인 추가

이 문서에서는 Spring Initializr와 Microsoft Entra용 Spring Boot Starter ID를 사용하여 로그인 기능이 있는 Java 앱을 만드는 방법을 보여줍니다.

이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.

  • Spring Initializr를 사용하여 Java 애플리케이션 만들기
  • Azure Active Directory B2C 구성
  • Spring Boot 클래스 및 주석을 사용하여 애플리케이션 보호
  • Java 애플리케이션 빌드 및 테스트

Microsoft Entra ID 는 Microsoft의 클라우드 규모 엔터프라이즈 ID 솔루션입니다. Azure Active Directory B2C 는 Microsoft Entra ID의 기능 집합을 보완하여 B2C(기업-소비자) 애플리케이션에 대한 고객, 소비자 및 시민 액세스를 관리할 수 있도록 합니다.

필수 구성 요소

Important

이 문서의 단계를 완료하려면 Spring Boot 버전 2.5 이상이 필요합니다.

Spring Initializr를 사용하여 앱 만들기

  1. https://start.spring.io/ 으로 이동합니다.

  2. 이 지침에 따라 값을 입력합니다. 레이블 및 레이아웃은 여기에 표시된 이미지와 다를 수 있습니다.

    • 프로젝트 아래에서 Maven 프로젝트를 선택합니다.
    • 언어에서 Java를 선택합니다.
    • Spring Boot에서 2.7.11을 선택합니다.
    • 그룹, 아티팩트이름에서 간단한 설명이 포함된 문자열을 사용하여 동일한 값을 입력합니다. UI는 입력할 때 이러한 필드 중 일부를 자동으로 채울 수 있습니다.
    • 종속성 창에서 종속성 추가를 선택합니다. UI를 사용하여 Spring 웹Spring 보안에 대한 종속성을 추가합니다.

    참고 항목

    Spring Security 5.5.1, 5.4.7, 5.3.10 및 5.2.11은 다음 CVE 보고서 CVE-2021-22119: spring-security-oauth2-client를 사용한 서비스 거부 공격을 해결하기 위해 릴리스되었습니다. 이전 버전을 사용하는 경우 업그레이드하세요.

  3. 프로젝트 생성을 선택한 다음, 로컬 컴퓨터의 경로에 프로젝트를 다운로드합니다. 다운로드한 파일을 프로젝트의 이름을 딴 디렉터리로 이동하고 파일의 압축을 풉 파일 레이아웃은 다음과 같아야 하며 그룹 대신 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 Portal을 사용하여 새 Azure Active Directory B2C 인스턴스를 만듭니다.

  3. 만들기를 실행합니다.

    Azure Active Directory B2C에 대한 Azure Marketplace 항목입니다.

  4. 새 Azure AD B2C 테넌트 만들기를 선택합니다.

    새 Azure AD B2C 테넌트를 만드는 Azure Portal 옵션입니다.

  5. 조직 이름초기 도메인 이름에 대해 적절한 값을 제공한 다음, 만들기를 선택합니다.

    Azure AD B2C 테넌트 만들기 화면

  6. Active Directory 만들기가 완료되면 오른쪽 위 모서리에서 계정을 선택하고 디렉터리 전환, 만든 디렉터리를 선택합니다. 새 테넌트 홈 페이지로 리디렉션됩니다. 그런 다음, Azure AD B2Cb2c 검색하여 선택합니다.

    Azure AD B2C 서비스를 찾습니다.

Spring Boot 앱에 대한 애플리케이션 등록 추가

  1. 관리 창에서 앱 등록 선택한 다음 새 등록을 선택합니다.

    Azure AD B2C 앱 등록 화면을 보여 주는 Azure Portal의 스크린샷.

  2. 이름 필드에 앱 이름을 입력한 다음, 등록을 선택합니다.

    Azure AD B2C는 애플리케이션 양식을 등록합니다.

  3. 관리 창으로 돌아가서 앱 등록 선택한 다음, 만든 애플리케이션 이름을 선택합니다.

    표시 이름이 선택된 앱 등록 화면입니다.

  4. 인증을 선택한 다음, 플랫폼을 추가한 다음 웹을 추가합니다. 리디렉션 URIhttp://localhost:8080/login/oauth2/code/로 설정한 다음, 구성을 선택합니다.

    인증을 위해 선택한 옵션, 플랫폼 추가, 웹

    리디렉션 URI 필드가 선택된 웹 화면을 구성합니다.

앱에 대한 앱 비밀 추가

인증서 및 비밀을 선택한 다음 새 클라이언트 비밀을 선택합니다. 비밀 설명을 입력한 다음, 추가를 선택합니다. 비밀을 만든 후 비밀 값 옆에 있는 복사 아이콘을 선택하여 이 문서의 뒷부분에서 사용할 값을 복사합니다.

클라이언트 암호 화면을 추가합니다.

복사 단추가 선택된 인증서 및 비밀 화면

참고 항목

인증서 및 비밀 섹션을 떠나 다시 돌아오면 비밀 값을 볼 수 없습니다. 이 경우 나중에 사용할 수 있도록 다른 비밀을 만들고 복사해야 합니다. application.yml 파일에 포함되면 문제가 되는 문자(예: 백슬래시 또는 백틱)가 생성된 비밀 값에 포함되는 경우가 있습니다. 이 경우 해당 비밀을 카드 다른 비밀을 생성합니다.

사용자 흐름 추가

  1. 테넌트 기본 페이지로 이동합니다. 왼쪽 창의 정책 섹션에서 사용자 흐름을 선택한 다음 새 사용자 흐름을 선택합니다.

  2. 이제 이 자습서를 떠나 다른 자습서를 실행하고 완료되면 이 자습서로 돌아갑니다. 다른 자습서로 이동하면 다음과 같은 사항에 유의해야 합니다.

    • 새 사용자 흐름을 선택하도록 요청하는 단계부터 시작합니다.
    • 이 자습서에서 참조하는 webapp1경우 그룹에 대해 입력한 값을 대신 사용합니다.
    • 흐름에서 반환할 클레임을 선택하는 경우 표시 이름이 선택되어 있는지 확인합니다. 이 클레임이 없으면 이 자습서에서 빌드되는 앱이 작동하지 않습니다.
    • 사용자 흐름을 실행하라는 메시지가 표시되면 이전에 지정한 리디렉션 URL이 아직 활성화되지 않았습니다. 흐름을 계속 실행할 수 있지만 리디렉션이 성공적으로 완료되지 않습니다. 예상된 동작입니다.
    • "다음 단계"에 도달하면 이 자습서로 돌아갑니다.

    자습서의 모든 단계를 수행합니다. Azure Active Directory B2C 에서 사용자 흐름을 만들어 "등록 및 로그인", "프로필 편집" 및 "암호 재설정"에 대한 사용자 흐름을 만듭니다.

    Azure AD B2C는 로컬 계정과 소셜 ID 공급자를 지원합니다. GitHub ID 공급자를 만드는 예제는 Azure Active Directory B2C를 사용하여 GitHub 계정으로 등록 및 로그인을 참조하세요.

앱 구성 및 컴파일

이제 Azure AD B2C 인스턴스 및 일부 사용자 흐름을 만들었으므로 Spring 앱을 Azure AD B2C 인스턴스에 연결합니다.

  1. 명령줄에서 cd를 사용하여 Spring Initializr에서 다운로드한 .zip 파일의 압축을 푼 디렉터리로 이동합니다.

  2. 프로젝트의 부모 폴더로 이동하고 텍스트 편집기에서 pom.xml Maven 프로젝트 파일을 엽니다.

  3. Spring OAuth2 보안의 종속성을 pom.xml에 추가합니다.

    <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들어 2.3.4.RELEASE위에서 선택한 Spring Boot 버전에 해당하는 버전을 사용합니다.

    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 작은따옴표로 묶입니다. 이는 YAML에 있을 때 작은따옴표 안에 있어야 하는 일부 문자가 <secret-value>의 값에 거의 확실히 포함되므로 필요합니다.

    참고 항목

    이 문서를 작성할 당시 application.yml에서 사용할 수 있는 Active Directory B2C Spring 통합 값의 전체 목록은 다음과 같습니다.

    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 샘플: GitHub의 aad-b2c-web-application에서 사용할 수 있습니다.

  7. application.yml 파일을 저장하고 닫습니다.

  8. src/기본/java/yourGroupId/<yourGroupId>>에< 컨트롤러라는 폴더를 만들고 그룹에 입력한 값으로 바꿔 <yourGroupId> 서 만듭니다.

  9. 컨트롤러 폴더에 WebController.javaJava 파일을 만들고 텍스트 편집기에서 엽니다.

  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());를 호출하므로 src/main/resources/templates의 모든 HTML 페이지에서 ${name}, ${grant_type} 또는 ${auth_time}과 같은 특성에 액세스할 수 있습니다. 반환된 user.getAttributes() 값은 실제로 인증에 대한 클레임 id_token 입니다. 사용 가능한 클레임의 전체 목록은 Microsoft ID 플랫폼 ID 토큰에 나열됩니다.

  11. src/기본/java/yourGroupId/<yourGroupId>>에< 보안이라는 폴더를 만들고 그룹에 입력한 값으로 바꿔 yourGroupId 서 만듭니다.

  12. 보안 폴더에 WebSecurityConfiguration.java이라는 새 Java 파일을 만들고 텍스트 편집기에서 엽니다.

  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. spring-cloud-azure-starter-active-directory-b2c 샘플인 aad-b2c-web-application 에서 src/기본/resources/templates로 home.html 파일을 복사하고 앞에서 만든 사용자 흐름의 이름으로 바꿉 ${your-password-reset-user-flow}${your-profile-edit-user-flow} 니다.

앱 빌드 및 테스트

  1. 명령 프롬프트를 열고 디렉터리를 앱의 pom.xml 파일이 위치한 폴더로 변경합니다.

  2. Maven을 사용하여 Spring Boot 애플리케이션을 빌드하고 실행합니다. 예를 들어:

    참고 항목

    로컬 스프링 부팅 앱이 실행되는 시스템 시계에 따른 시간이 정확하다는 것은 매우 중요합니다. OAuth 2.0을 사용하는 경우 클록 기울이기의 허용 오차가 거의 없습니다. 3분 동안의 부정확성으로 인해 로그인이 실패하고 다음과 유사한 [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에서 사용자 흐름 만들기에서 만든 사용자 워크플로를 다시 확인합니다. 사용자 워크플로를 만들 때 사용자 특성 및 클레임에 대해 표시 이름에 대한 특성 및 클레임을 선택해야 합니다. 또한 application.yml 파일에서 제대로 구성 user-name-attribute-name 해야 합니다.

B2C 엔드포인트에 루프를 사용하여 로그인

이 문제는 대부분 localhost에 대한 오염된 쿠키로 인해 발생합니다. 쿠키를 localhost 정리하고 다시 시도하십시오.

요약

이 자습서에서는 Azure Active Directory B2C 스타터를 사용하여 새 Java 웹 애플리케이션을 만들고, 새 Azure AD B2C 테넌트를 구성하고, 새 애플리케이션을 등록한 다음, Spring 주석 및 클래스를 사용하여 웹앱을 보호하도록 애플리케이션을 구성했습니다.

리소스 정리

더 이상 필요하지 않은 경우 예기치 않은 요금을 방지하기 위해 Azure Portal을 사용하여 이 문서에서 만든 리소스를 삭제합니다.

다음 단계

Spring과 Azure에 대한 자세한 사항은 Azure의 Spring 설명서 센터를 참조합니다.