Spring Security용 Spring Cloud Azure 지원

이 문서는 버전 4.14.0 ✔️ 버전 5.8.0에 적용됩니다. ✔️

이 문서에서는 Spring Cloud Azure와 Spring Security를 함께 사용하는 방법을 설명합니다.

Microsoft Entra ID를 사용하는 Spring Security

웹 애플리케이션을 빌드할 때 ID 및 액세스 관리는 항상 기본 요소입니다.

Azure는 클라우드 기반 ID 서비스뿐만 아니라 나머지 Azure 에코시스템과의 긴밀한 통합을 제공하므로 애플리케이션 개발 과정을 민주화할 수 있는 훌륭한 플랫폼을 제공합니다.

Spring Security를 사용하면 강력한 추상화 및 확장 가능한 인터페이스를 사용하여 Spring 기반 애플리케이션을 쉽게 보호할 수 있습니다. 그러나 Spring 프레임워크만큼 강력하지만 특정 ID 공급자에 맞게 조정되지는 않습니다.

spring-cloud-azure-starter-active-directory 애플리케이션을 Microsoft Entra ID(짧은 경우 Microsoft Entra ID) 테넌트에 연결하고 Microsoft Entra ID로 리소스 서버를 보호하는 가장 최적의 방법을 제공합니다. Oauth 2.0 프로토콜을 사용하여 웹 애플리케이션 및 리소스 서버를 보호합니다.

웹 애플리케이션 액세스

이 시나리오에서는 OAuth 2.0 인증 코드 부여 흐름을 사용하여 Microsoft 계정으로 사용자를 로그인합니다.

시스템 다이어그램

System diagram for a standalone web application.

Azure에서 필요한 리소스 만들기

  1. 빠른 시작 읽기: Microsoft ID 플랫폼 애플리케이션을 등록합니다.

  2. 앱 등록을 만듭니다. 가져오기 AZURE_TENANT_ID, AZURE_CLIENT_IDAZURE_CLIENT_SECRET.

  3. 로 설정 redirect URI - 예를 들면 다음과 같습니다http://localhost:8080/login/oauth2/code/.APPLICATION_BASE_URI/login/oauth2/code/ 테일링 / 이 필요합니다.

필수 종속성 추가

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>

필수 속성 추가

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}

참고 항목

허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 - ID 공급자의 사용자 계정이 테넌트에 존재하지 않는 잘못된 엔드포인트(개인 및 조직 계정) 사용 섹션을 참조하세요. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID에서 단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

이제 애플리케이션을 시작하고 브라우저를 통해 애플리케이션에 액세스합니다. Microsoft 로그인 페이지로 리디렉션됩니다.

고급 사용량

추가 보안 구성 추가
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadOAuth2LoginSecurityConfig extends AadWebSecurityConfigurerAdapter {

    /**
     * Add configuration logic as needed.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests()
                .anyRequest().authenticated();
        // Do some custom configuration
    }
}
앱 역할별 액세스 권한 부여

Azure에서 필요한 리소스를 만듭니다.

  • 애플리케이션에 앱 역할 추가를 읽고 토큰에서 받습니다.

  • 다음 매개 변수를 사용하여 앱 역할을 만듭니다.

    • 표시 이름: 관리
    • 허용되는 멤버 유형: 사용자/그룹
    • 값: 관리
    • 이 앱 역할을 사용하도록 설정하시겠습니까? 예

참고 항목

앱 역할 기반 액세스 제어를 사용하려는 경우 클레임에 role 그룹 이름을 넣을 수 없습니다. 자세한 내용은 앱에 선택적 클레임 제공의 그룹 선택적 클레임 구성 섹션을 참조하세요.

특정 메서드를 보호합니다.

class Demo {
   @GetMapping("Admin")
   @ResponseBody
   @PreAuthorize("hasAuthority('APPROLE_Admin')")
   public String admin() {
       return "Admin message";
   }
}
그룹 이름 또는 그룹 ID별 액세스 권한 부여

관련 구성 속성을 추가합니다.

spring:
 cloud:
   azure:
     active-directory:
       enabled: true
       user-group:
         allowed-group-names: group1_name_1, group2_name_2
         # 1. If allowed-group-ids == all, then all group ID will take effect.
         # 2. If "all" is used, we should not configure other group ids.
         # 3. "all" is only supported for allowed-group-ids, not supported for allowed-group-names.
         allowed-group-ids: group_id_1, group_id_2

특정 메서드를 보호합니다.

@Controller
public class RoleController {
   @GetMapping("group1")
   @ResponseBody
   @PreAuthorize("hasRole('ROLE_group1')")
   public String group1() {
       return "group1 message";
   }

   @GetMapping("group2")
   @ResponseBody
   @PreAuthorize("hasRole('ROLE_group2')")
   public String group2() {
       return "group2 message";
   }

   @GetMapping("group1Id")
   @ResponseBody
   @PreAuthorize("hasRole('ROLE_<group1-id>')")
   public String group1Id() {
       return "group1Id message";
   }

   @GetMapping("group2Id")
   @ResponseBody
   @PreAuthorize("hasRole('ROLE_<group2-id>')")
   public String group2Id() {
       return "group2Id message";
   }
}
글로벌 Azure 대신 National Azure 사용

이제 글로벌 Azure 클라우드를 제외하고 Microsoft Entra ID는 다음 국가별 클라우드에 배포됩니다.

  • Azure Government

  • Azure 중국 21Vianet

  • Azure 독일

다음은 Azure 중국 21Vianet을 사용하는 샘플입니다.

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        base-uri: https://login.partner.microsoftonline.cn
        graph-base-uri: https://microsoftgraph.chinacloudapi.cn

자세한 내용은 국가별 클라우드 배포를 참조 하세요.

리디렉션 URI 템플릿 구성

개발자는 redirect-uri를 사용자 지정할 수 있습니다.

System diagram for redirect URIs.

application.yml 파일에 속성을 추가 redirect-uri-template 합니다.

spring:
 cloud:
   azure:
     active-directory:
       enabled: true
       redirect-uri-template: ${REDIRECT-URI-TEMPLATE}

Azure Portal에서 업데이트 redirect-uri 합니다.

Configure Redirect URI Template.

설정한 redirect-uri-template후에는 보안 작성기를 업데이트해야 합니다.

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadOAuth2LoginSecurityConfig extends AadWebSecurityConfigurerAdapter {
    /**
     * Add configuration logic as needed.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.oauth2Login()
                .loginProcessingUrl("${REDIRECT-URI-TEMPLATE}")
                .and()
            .authorizeRequests()
                .anyRequest().authenticated();
    }
}

프록시를 통해 Microsoft Entra ID로 커넥트

프록시를 통해 Microsoft Entra ID를 RestTemplateCustomizer 연결하려면 다음 예제와 같이 콩을 제공합니다.

@Configuration
class DemoConfiguration {
    @Bean
    public RestTemplateCustomizer proxyRestTemplateCustomizer() {
        return (RestTemplate restTemplate) -> {
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_SERVER_HOST, PROXY_SERVER_PORT));
            SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            requestFactory.setProxy(proxy);
            restTemplate.setRequestFactory(requestFactory);
        };
    }
}

샘플

샘플 프로젝트: aad-web-application.

리소스 서버에 액세스하는 웹 애플리케이션

시스템 다이어그램

System diagram for a web application accessing resource servers.

Azure에서 필수 리소스 만들기

  1. 빠른 시작 읽기: Microsoft ID 플랫폼 애플리케이션을 등록합니다.

  2. 앱 등록을 만듭니다. 가져오기 AZURE_TENANT_ID, AZURE_CLIENT_IDAZURE_CLIENT_SECRET.

  3. 예를 들어 http://localhost:8080/login/oauth2/code/.로 APPLICATION_BASE_URI/login/oauth2/code/설정합니다redirect URI. 테일링 / 이 필요합니다.

필수 종속성 추가

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>

필수 속성 추가

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          graph:
            scopes: https://graph.microsoft.com/Analytics.Read, email

참고 항목

허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 - ID 공급자의 사용자 계정이 테넌트에 존재하지 않는 잘못된 엔드포인트(개인 및 조직 계정) 사용 섹션을 참조하세요. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID에서 단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

graph 여기서 이름은 OAuth2AuthorizedClientscopes 로그인할 때 동의해야 하는 범위를 의미합니다.

애플리케이션에서 OAuth2AuthorizedClient 사용

public class Demo {
    @GetMapping("/graph")
    @ResponseBody
    public String graph(
    @RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graphClient) {
        // toJsonString() is just a demo.
        // oAuth2AuthorizedClient contains access_token. We can use this access_token to access resource server.
        return toJsonString(graphClient);
    }
}

이제 애플리케이션을 시작하고 브라우저에서 애플리케이션에 액세스합니다. 그런 다음 Microsoft 로그인 페이지로 리디렉션됩니다.

고급 사용량

클라이언트 자격 증명 흐름

기본 흐름은 권한 부여 코드 흐름입니다. 클라이언트 자격 증명 흐름을 사용하려는 경우 다음과 같이 구성할 수 있습니다.

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          graph:
            authorization-grant-type: client_credentials # Change type to client_credentials
            scopes: https://graph.microsoft.com/Analytics.Read, email

참고 항목

허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 - ID 공급자의 사용자 계정이 테넌트에 존재하지 않는 잘못된 엔드포인트(개인 및 조직 계정) 사용 섹션을 참조하세요. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID에서 단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

여러 리소스 서버에 액세스

한 웹 애플리케이션에서 다음과 같이 구성하여 여러 리소스 서버에 액세스할 수 있습니다.

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          resource-server-1:
            scopes: # Scopes for resource-server-1
          resource-server-2:
            scopes: # Scopes for resource-server-2

참고 항목

허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 - ID 공급자의 사용자 계정이 테넌트에 존재하지 않는 잘못된 엔드포인트(개인 및 조직 계정) 사용 섹션을 참조하세요. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID에서 단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

그런 다음 다음과 같이 애플리케이션에서 사용할 OAuth2AuthorizedClient 수 있습니다.

public class Demo {
    @GetMapping("/resource-server-1")
    @ResponseBody
    public String graph(
    @RegisteredOAuth2AuthorizedClient("resource-server-1") OAuth2AuthorizedClient client) {
        return callResourceServer1(client);
    }

    @GetMapping("/resource-server-2")
    @ResponseBody
    public String graph(
    @RegisteredOAuth2AuthorizedClient("resource-server-2") OAuth2AuthorizedClient client) {
        return callResourceServer2(client);
    }
}

샘플

샘플 프로젝트: aad-web-application.

리소스 서버 액세스

이 시나리오는 로그인을 지원하지 않고 액세스 토큰의 유효성을 검사하여 서버를 보호합니다. 액세스 토큰이 유효한 경우 서버는 요청을 제공합니다.

시스템 다이어그램

System diagram for standalone resource server usage.

Azure에서 필요한 리소스 만들기

  1. 빠른 시작 읽기: Microsoft ID 플랫폼 애플리케이션을 등록합니다.

  2. 앱 등록을 만듭니다. 를 가져옵니다 AZURE_CLIENT_ID.

  3. 빠른 시작 읽기 : 웹 API를 노출하도록 애플리케이션을 구성합니다.

  4. 이름이 지정된 Scope-1범위가 있는 웹 API를 노출합니다.

필수 종속성 추가

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
</dependencies>

필수 속성 추가

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        credential:
          client-id: ${AZURE_CLIENT_ID}

이제 애플리케이션을 시작하고 애플리케이션의 웹 API에 액세스합니다.

  1. 액세스 토큰 없이 401을 받게 됩니다.

  2. 액세스 토큰을 사용하여 애플리케이션에 액세스합니다. 액세스 토큰에서 다음 클레임의 유효성이 검사됩니다.

    • iss: Microsoft Entra ID를 통해 액세스 토큰을 발급해야 합니다.

    • nbf: 현재 시간은 이전 nbf일 수 없습니다.

    • exp: 현재 시간은 다음을 수행할 수 없습니다 exp.

    • aud: 구성되었거나 구성된 대상 spring.cloud.azure.active-directory.credential.client-id 은 구성된 client-id 대상 그룹 또는 app-id-uri.1과 같아야 spring.cloud.azure.active-directory.credential.app-id-uri 합니다. 두 속성이 구성되지 않으면 이 클레임의 유효성이 검사되지 않습니다.

액세스 토큰에 대한 자세한 내용은 Microsoft ID 플랫폼 액세스 토큰에 대한 MS 문서를 참조하세요.

고급 사용량

추가 보안 구성 추가
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadOAuth2ResourceServerSecurityConfig extends AadResourceServerWebSecurityConfigurerAdapter {
    /**
     * Add configuration logic as needed.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
    }
}
범위별 권한 유효성 검사
  1. Azure에서 필요한 리소스를 만듭니다.

    • 빠른 시작 읽기 : 웹 API를 노출하도록 애플리케이션을 구성합니다.

    • 이름이 지정된 Scope1범위가 있는 웹 API를 노출합니다.

  2. 특정 메서드를 보호합니다.

    class Demo {
        @GetMapping("scope1")
        @ResponseBody
        @PreAuthorize("hasAuthority('SCOPE_Scope1')")
        public String scope1() {
            return "Congratulations, you can access `scope1` endpoint.";
        }
    }
    

이렇게 하면 액세스 엔드포인트에 액세스할 /scope1 때 액세스 토큰에서 다음 클레임의 유효성이 검사됩니다.

  • scp: 값에 을 포함 Scope1해야 합니다.
앱 역할별 권한 유효성 검사
  1. Azure에서 필요한 리소스를 만듭니다.

    • 애플리케이션에 앱 역할 추가를 읽고 토큰에서 받습니다.

    • 다음 매개 변수를 사용하여 앱 역할을 만듭니다.

      • 표시 이름: AppRole1
      • 허용되는 멤버 유형: 사용자/그룹
      • 값: AppRole1
      • 이 앱 역할을 사용하도록 설정하시겠습니까? 예
  2. 특정 메서드를 보호합니다.

    class Demo {
        @GetMapping("app-role1")
        @ResponseBody
        @PreAuthorize("hasAuthority('APPROLE_AppRole1')")
        public String appRole1() {
            return "Congratulations, you can access `app-role1` endpoint.";
        }
    }
    

이렇게 하면 액세스 엔드포인트에 액세스할 /app-role1 때 액세스 토큰에서 다음 클레임의 유효성이 검사됩니다.

  • roles: 값에 을 포함 AppRole1해야 합니다.
JWT 클라이언트 인증 사용

클라이언트 인증에 JWT(JSON 웹 토큰)를 사용하려면 다음 단계를 사용합니다.

  1. Microsoft ID 플랫폼 애플리케이션 인증 인증서 자격 증명Microsoft ID 플랫폼 섹션을 사용하여 인증서 등록을 참조하세요.
  2. Azure Portal에 등록된 애플리케이션에 .pem 인증서를 업로드합니다.
  3. 의 인증서 경로 및 암호를 구성합니다 . PFX 또는 . P12 인증서.
  4. JWT 클라이언트 인증을 통해 인증할 클라이언트에 속성 spring.cloud.azure.active-directory.authorization-clients.azure.client-authentication-method=private_key_jwt 구성을 추가합니다.

다음 예제 구성 파일은 웹 애플리케이션 시나리오용입니다. 인증서 정보는 전역 속성에 구성됩니다.

spring:
  cloud:
    azure:
      credential:
        client-id: ${AZURE_CLIENT_ID}
        client-certificate-path: ${AZURE_CERTIFICATE_PATH}
        client-certificate-password: ${AZURE_CERTIFICATE_PASSWORD}
      profile:
        tenant-id: <tenant>
      active-directory:
        enabled: true
        user-group:
          allowed-group-names: group1,group2
          allowed-group-ids: <group1-id>,<group2-id>
        post-logout-redirect-uri: http://localhost:8080
        authorization-clients:
          azure:
            client-authentication-method: private_key_jwt
          arm:
            client-authentication-method: private_key_jwt
            scopes: https://management.core.windows.net/user_impersonation
          graph:
            client-authentication-method: private_key_jwt
            scopes:
              - https://graph.microsoft.com/User.Read
              - https://graph.microsoft.com/Directory.Read.All
          webapiA:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_A_APP_ID_URL}/Obo.WebApiA.ExampleScope
          webapiB:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_B_APP_ID_URL}/.default
            authorization-grant-type: client_credentials

참고 항목

허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 - ID 공급자의 사용자 계정이 테넌트에 존재하지 않는 잘못된 엔드포인트(개인 및 조직 계정) 사용 섹션을 참조하세요. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID에서 단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

이 예제와 같이 서비스 속성에서 active-directory 인증서 정보를 구성할 수도 있습니다.

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-certificate-path: ${AZURE_CERTIFICATE_PATH}
          client-certificate-password: ${AZURE_CERTIFICATE_PASSWORD}
        profile:
          tenant-id: <tenant>
        user-group:
          allowed-group-names: group1,group2
          allowed-group-ids: <group1-id>,<group2-id>
        post-logout-redirect-uri: http://localhost:8080
        authorization-clients:
          azure:
            client-authentication-method: private_key_jwt
          arm:
            client-authentication-method: private_key_jwt
            scopes: https://management.core.windows.net/user_impersonation
          graph:
            client-authentication-method: private_key_jwt
            scopes:
              - https://graph.microsoft.com/User.Read
              - https://graph.microsoft.com/Directory.Read.All
          webapiA:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_A_APP_ID_URL}/Obo.WebApiA.ExampleScope
          webapiB:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_B_APP_ID_URL}/.default
            authorization-grant-type: client_credentials

참고 항목

허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 - ID 공급자의 사용자 계정이 테넌트에 존재하지 않는 잘못된 엔드포인트(개인 및 조직 계정) 사용 섹션을 참조하세요. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID에서 단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

프록시를 통해 Microsoft Entra ID로 커넥트

프록시를 통해 Microsoft Entra ID를 연결하려면 콩을 RestTemplateCustomizer 제공합니다. 자세한 내용은 프록시 섹션을 통해 Microsoft Entra ID에 대한 커넥트 참조하세요.

샘플

샘플 프로젝트: aad-resource-server.

다른 리소스 서버를 방문하는 리소스 서버

시스템 다이어그램

System diagram for a resource server visiting other resource servers.

Azure에서 필요한 리소스 만들기

  1. 빠른 시작 읽기: Microsoft ID 플랫폼 애플리케이션을 등록합니다.

  2. 앱 등록을 만듭니다. 가져오기 AZURE_TENANT_ID, AZURE_CLIENT_IDAZURE_CLIENT_SECRET.

필수 종속성 추가

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>

필수 속성 추가

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          graph:
            scopes:
              - https://graph.microsoft.com/User.Read

참고 항목

허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 - ID 공급자의 사용자 계정이 테넌트에 존재하지 않는 잘못된 엔드포인트(개인 및 조직 계정) 사용 섹션을 참조하세요. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID에서 단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

애플리케이션에서 OAuth2AuthorizedClient 사용

public class SampleController {
    @GetMapping("call-graph")
    public String callGraph(@RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graph) {
        return callMicrosoftGraphMeEndpoint(graph);
    }
}

샘플

샘플 프로젝트: aad-resource-server-obo.

하나의 애플리케이션에서 웹 애플리케이션 및 리소스 서버

Azure에서 필요한 리소스 만들기

  1. 빠른 시작 읽기: Microsoft ID 플랫폼 애플리케이션을 등록합니다.

  2. 앱 등록을 만듭니다. 가져오기 AZURE_TENANT_ID, AZURE_CLIENT_IDAZURE_CLIENT_SECRET.

필수 종속성 추가

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>

필수 속성 추가

속성을 spring.cloud.azure.active-directory.application-typeweb_application_and_resource_server설정하고 각 권한 부여 클라이언트에 대한 권한 부여 유형을 지정합니다.

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        app-id-uri: ${WEB_API_ID_URI}
        application-type: web_application_and_resource_server  # This is required.
        authorization-clients:
          graph:
            authorizationGrantType: authorization_code # This is required.
            scopes:
              - https://graph.microsoft.com/User.Read
              - https://graph.microsoft.com/Directory.Read.All

참고 항목

허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 - ID 공급자의 사용자 계정이 테넌트에 존재하지 않는 잘못된 엔드포인트(개인 및 조직 계정) 사용 섹션을 참조하세요. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID에서 단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

SecurityFilterChain 정의

여러 SecurityFilterChain 인스턴스를 구성합니다. AadWebApplicationAndResourceServerConfig 에는 리소스 서버 및 웹 애플리케이션에 대한 두 가지 보안 필터 체인 구성이 포함되어 있습니다.

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadWebApplicationAndResourceServerConfig {

    @Order(1)
    @Configuration
    public static class ApiWebSecurityConfigurationAdapter extends AadResourceServerWebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception {
            super.configure(http);
            // All the paths that match `/api/**`(configurable) work as `Resource Server`, other paths work as `Web application`.
            http.antMatcher("/api/**")
                .authorizeRequests().anyRequest().authenticated();
        }
    }

    @Configuration
    public static class HtmlWebSecurityConfigurerAdapter extends AadWebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            super.configure(http);
            // @formatter:off
            http.authorizeRequests()
                    .antMatchers("/login").permitAll()
                    .anyRequest().authenticated();
            // @formatter:on
        }
    }
}

구성

spring-cloud-azure-starter-active-directory의 구성 가능한 속성:

이름 설명
spring.cloud.azure.active-directory.app-id-uri id_token "aud" 클레임에 사용될 수 있는 앱 ID URI입니다.
spring.cloud.azure.active-directory.application-type Microsoft Entra 애플리케이션의 유형입니다.
spring.cloud.azure.active-directory.authenticate-additional-parameters 권한 부여 URL에 매개 변수를 추가합니다.
spring.cloud.azure.active-directory.authorization-clients OAuth2 권한 부여 클라이언트입니다.
spring.cloud.azure.active-directory.credential.client-id Azure에서 서비스 주체 인증을 수행할 때 사용할 클라이언트 ID입니다.
spring.cloud.azure.active-directory.credential.client-secret Azure에서 서비스 주체 인증을 수행할 때 사용할 클라이언트 암호입니다.
spring.cloud.azure.active-directory.jwk-set-cache-lifespan 만료되기 전에 캐시된 JWK 집합의 수명은 기본값인 5분입니다.
spring.cloud.azure.active-directory.jwk-set-cache-refresh-time 캐시된 JWK가 만료되기 전에 설정한 새로 고침 시간(기본값은 5분)입니다.
spring.cloud.azure.active-directory.jwt-connect-timeout JWKSet 원격 URL 호출에 대한 커넥트ion 시간 제한입니다.
spring.cloud.azure.active-directory.jwt-read-timeout JWKSet 원격 URL 호출에 대한 시간 제한을 읽습니다.
spring.cloud.azure.active-directory.jwt-size-limit JWKSet 원격 URL 호출의 크기 제한(바이트)입니다.
spring.cloud.azure.active-directory.post-logout-redirect-uri 로그아웃 후 리디렉션 URI입니다.
spring.cloud.azure.active-directory.profile.cloud-type 연결할 Azure 클라우드의 이름입니다. 지원되는 형식은 AZURE, AZURE_CHINA, AZURE_GERMANY, AZURE_US_GOVERNMENT, OTHER입니다.
spring.cloud.azure.active-directory.profile.environment Microsoft Entra 엔드포인트에 대한 속성입니다.
spring.cloud.azure.active-directory.profile.tenant-id Azure 테넌트 ID입니다. 허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다.
spring.cloud.azure.active-directory.redirect-uri-template 리디렉션 엔드포인트: 권한 부여 서버에서 리소스 소유자 사용자 에이전트를 통해 권한 부여 자격 증명이 포함된 응답을 클라이언트에 반환하는 데 사용됩니다. 기본값은 {baseUrl}/login/oauth2/code/입니다.
spring.cloud.azure.active-directory.resource-server.claim-to-authority-prefix-map GrantedAuthority를 빌드하는 데 사용할 클레임과 GrantedAuthority 문자열 값의 접두사를 구성합니다. 기본값은 "scp" -> "SCOPE_", "roles" -> "APPROLE_"입니다.
spring.cloud.azure.active-directory.resource-server.principal-claim-name AuthenticatedPrincipal#getName에서 반환될 액세스 토큰의 클레임을 구성합니다. 기본값은 "sub"입니다.
spring.cloud.azure.active-directory.session-stateless true이면 상태 비정상 인증 필터 AadAppRoleStatelessAuthenticationFilter를 활성화합니다. 기본값은 AadAuthenticationFilter를 활성화하는 false입니다.
spring.cloud.azure.active-directory.user-group.allowed-group-ids 그룹 ID를 사용하여 GrantedAuthority를 생성할 수 있습니다.
spring.cloud.azure.active-directory.user-group.allowed-group-names 그룹 이름을 사용하여 GrantedAuthority를 생성할 수 있습니다.
spring.cloud.azure.active-directory.user-group.use-transitive-members "true"이면 "v1.0/me/transitiveMemberOf"를 사용하여 멤버를 가져옵니다. 그렇지 않으면 "v1.0/me/memberOf"를 사용합니다. 기본값은 false입니다.
spring.cloud.azure.active-directory.user-name-attribute 보안 주체의 이름이 될 클레임을 결정합니다.

이러한 속성을 사용하는 방법에 대한 몇 가지 예는 다음과 같습니다.

응용 프로그램 유형

애플리케이션 유형은 종속성에서 유추할 수 있습니다. spring-security-oauth2-client 또는 spring-security-oauth2-resource-server. 유추된 값이 원하는 값이 아닌 경우 애플리케이션 유형을 지정할 수 있습니다. 유효한 값과 유추된 값의 테이블은 다음과 같습니다.

애플리케이션 유형 spring-cloud-azure-starter-active-directory:

종속성이 있습니다. spring-security-oauth2-client 종속성이 있습니다. spring-security-oauth2-resource-server 애플리케이션 종류의 유효한 값 유추된 값
없음 web_application web_application
없음 resource_server resource_server
web_application, resource_server, resource_server_with_obo, web_application_and_resource_server resource_server_with_obo

Azure Active Directory B2C를 사용하는 Spring Security

Azure AD(Azure Active Directory) B2C는 고객이 애플리케이션을 사용할 때 자신의 프로필을 등록, 로그인 및 관리하는 방법을 사용자 지정하고 제어할 수 있는 ID 관리 서비스입니다. Azure AD B2C를 사용하면 고객의 ID를 보호하면서 이러한 작업을 수행할 수 있습니다.

종속성 설정

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory-b2c</artifactId>
    </dependency>
</dependencies>

구성

spring-cloud-azure-starter-active-directory-b2c의 구성 가능한 속성:

이름 설명
spring.cloud.azure.active-directory.b2c.app-id-uri 토큰의 "aud" 클레임에 사용될 수 있는 앱 ID URI입니다.
spring.cloud.azure.active-directory.b2c.authenticate-additional-parameters 인증에 대한 추가 매개 변수입니다.
spring.cloud.azure.active-directory.b2c.authorization-clients 클라이언트 구성을 지정합니다.
spring.cloud.azure.active-directory.b2c.base-uri Azure AD B2C 엔드포인트 기본 URI.
spring.cloud.azure.active-directory.b2c.credential Azure AD B2C 자격 증명 정보입니다.
spring.cloud.azure.active-directory.b2c.jwt-connect-timeout JWKSet 원격 URL 호출에 대한 커넥트ion 시간 제한입니다.
spring.cloud.azure.active-directory.b2c.jwt-read-timeout JWKSet 원격 URL 호출에 대한 시간 제한을 읽습니다.
spring.cloud.azure.active-directory.b2c.jwt-size-limit JWKSet 원격 URL 호출의 크기 제한(바이트)입니다.
spring.cloud.azure.active-directory.b2c.login-flow 기본 로그인 흐름 키를 지정합니다. 기본값은 sign-up-or-sign-in입니다.
spring.cloud.azure.active-directory.b2c.logout-success-url 로그아웃 후 URL을 리디렉션합니다. 기본값은 http://localhost:8080/login입니다.
spring.cloud.azure.active-directory.b2c.profile Azure AD B2C 프로필 정보입니다.
spring.cloud.azure.active-directory.b2c.reply-url 권한 부여 코드를 받은 후 회신 URL입니다. 기본값은 {baseUrl}/login/oauth2/code/입니다.
spring.cloud.azure.active-directory.b2c.user-flows 사용자 흐름.
spring.cloud.azure.active-directory.b2c.user-name-attribute-name 사용자 이름 특성 이름입니다.

전체 구성의 경우 Spring Cloud Azure 구성 속성을 검사.

기본 사용법

웹 애플리케이션은 사용자가 Microsoft Entra ID로 로그인할 수 있는 웹 기반 애플리케이션인 반면, 리소스 서버는 Microsoft Entra ID에서 가져온 access_token 유효성을 검사한 후 액세스를 허용하거나 거부합니다. 이 가이드에서는 4가지 시나리오를 다룹니다.

  1. 웹 애플리케이션에 액세스합니다.

  2. 리소스 서버에 액세스하는 웹 애플리케이션입니다.

  3. 리소스 서버에 액세스합니다.

  4. 다른 리소스 서버에 액세스하는 리소스 서버입니다.

System diagram of web application interaction with Microsoft Entra ID and resource servers.

사용량 1: 웹 애플리케이션 액세스

이 시나리오에서는 OAuth 2.0 권한 부여 코드 부여 흐름을 사용하여 Azure AD B2C 사용자로 사용자를 로그인합니다.

포털 메뉴에서 Azure AD B2C를 선택하고 애플리케이션을 선택한 다음 추가를 선택합니다.

애플리케이션 이름(예: webapp회신 URL에 추가 http://localhost:8080/login/oauth2/code/)을 지정하고 애플리케이션 ID사용자WEB_APP_AZURE_CLIENT_ID로 기록한 다음 저장을 선택합니다 .

애플리케이션에서 키를 선택하고, 생성할 키 생성을 WEB_APP_AZURE_CLIENT_SECRET선택한 다음, 저장을 선택합니다.

왼쪽에서 사용자 흐름을 선택한 다음 새 사용자 흐름을 선택합니다.

등록 또는 로그인, 프로필 편집암호 재설정을 선택하여 각각 사용자 흐름을 만듭니다. 사용자 흐름 이름사용자 특성 및 클레임을 지정한 다음 만들기를 선택합니다.

API 사용 권한>Microsoft API>추가, Microsoft Graph 선택, 위임된 사용 권한 선택, offline_accessopenid 권한 선택, 프로세스 완료를 위한 권한 추가를 선택합니다.

Graph 권한에 대한 관리자 동의를 부여합니다.

Azure portal screenshot showing API permissions screen for an app, with graph permissions highlighted.

pom.xml 파일에 다음 종속성을 추가합니다.

<dependencies>
   <dependency>
       <groupId>com.azure.spring</groupId>
       <artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-thymeleaf</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-security</artifactId>
   </dependency>
   <dependency>
       <groupId>org.thymeleaf.extras</groupId>
       <artifactId>thymeleaf-extras-springsecurity5</artifactId>
   </dependency>
</dependencies>

다음 예제와 같이 앞에서 만든 값을 사용하여 application.yml 파일에 속성을 추가합니다.

spring:
 cloud:
   azure:
     active-directory:
       b2c:
         enabled: true
         authenticate-additional-parameters:
           domain_hint: xxxxxxxxx         # optional
           login_hint: xxxxxxxxx          # optional
           prompt: [login,none,consent]   # optional
         base-uri: ${BASE_URI}
         credential:
           client-id: ${WEBAPP_AZURE_CLIENT_ID}
           client-secret: ${WEBAPP_AZURE_CLIENT_SECRET}
         login-flow: ${LOGIN_USER_FLOW_KEY}               # default to sign-up-or-sign-in, will look up the user-flows map with provided key.
         logout-success-url: ${LOGOUT_SUCCESS_URL}
         user-flows:
           ${YOUR_USER_FLOW_KEY}: ${USER_FLOW_NAME}
         user-name-attribute-name: ${USER_NAME_ATTRIBUTE_NAME}

Java 코드를 작성합니다.

컨트롤러 코드의 경우 다음 예제를 참조할 수 있습니다.

@Controller
public class WebController {

   private void initializeModel(Model model, OAuth2AuthenticationToken token) {
       if (token != null) {
           final OAuth2User user = token.getPrincipal();
           model.addAllAttributes(user.getAttributes());
           model.addAttribute("grant_type", user.getAuthorities());
           model.addAttribute("name", user.getName());
       }
   }

   @GetMapping(value = { "/", "/home" })
   public String index(Model model, OAuth2AuthenticationToken token) {
       initializeModel(model, token);
       return "home";
   }
}

보안 구성 코드의 경우 다음 예제를 참조할 수 있습니다.

@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 {
       // @formatter:off
       http.authorizeRequests()
               .anyRequest().authenticated()
               .and()
           .apply(configurer);
       // @formatter:off
   }
}

aad-b2c-web-application 샘플에서 home.html을 복사하고 이전에 사용한 사용자 흐름 이름으로 바꿉 PROFILE_EDIT_USER_FLOWPASSWORD_RESET_USER_FLOW 니다.

앱을 빌드하고 테스트합니다. 포트 8080에서 실행합니다Webapp.

Maven에서 애플리케이션을 빌드하고 시작한 후 웹 브라우저에서 엽니다 http://localhost:8080/ . 로그인 페이지로 리디렉션되어야 합니다.

로그인 사용자 흐름이 있는 링크를 선택합니다. 인증 프로세스를 시작하려면 Azure AD B2C를 리디렉션해야 합니다.

성공적으로 로그인하면 브라우저에서 샘플 home page 이 표시됩니다.

사용량 2: 리소스 서버에 액세스하는 웹 애플리케이션

이 시나리오는 애플리케이션이 다른 리소스에 액세스할 수 있도록 하는 웹 애플리케이션 액세스 시나리오를 기반으로 합니다. 이 시나리오는 OAuth 2.0 클라이언트 자격 증명 부여 흐름입니다.

포털 메뉴에서 Azure AD B2C를 선택하고 애플리케이션을 선택한 다음 추가를 선택합니다.

애플리케이션 이름(예: webApiA)을 지정하고 애플리케이션 ID사용자WEB_API_A_AZURE_CLIENT_ID로 기록한 다음 저장을 선택합니다.

애플리케이션에서 키를 선택하고, 생성할 키 생성을 WEB_API_A_AZURE_CLIENT_SECRET선택한 다음, 저장을 선택합니다.

탐색 창에서 API 노출을 선택한 다음, [설정]을 선택합니다. 애플리케이션 ID URI사용자WEB_API_A_APP_ID_URL로 기록한 다음 저장을 선택합니다.

탐색 창에서 매니페스트를 선택한 다음, 다음 JSON 세그먼트를 배열에 붙여넣습니다appRoles. 애플리케이션 ID URI를 사용자WEB_API_A_APP_ID_URL로 기록하고 앱 역할의 값을 사용자WEB_API_A_ROLE_VALUE로 기록한 다음 저장을 선택합니다.

{
 "allowedMemberTypes": [
   "Application"
 ],
 "description": "WebApiA.SampleScope",
 "displayName": "WebApiA.SampleScope",
 "id": "04989db0-3efe-4db6-b716-ae378517d2b7",
 "isEnabled": true,
 "value": "WebApiA.SampleScope"
}

Azure portal screenshot showing application manifest screen with appRoles JSON highlighted.

API 사용 권한> API>추가, WebApiA 애플리케이션 이름 선택, 애플리케이션 사용 권한 선택, WebApiA.SampleScope 권한 선택, 프로세스 완료를 위한 권한 추가를 선택합니다.

WebApiA 권한에 대한 관리자 동의를 부여합니다.

Azure portal screenshot showing application API permissions screen.

웹 애플리케이션 액세스 시나리오를 기반으로 다음 종속성을 추가합니다.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

웹 애플리케이션 액세스 시나리오를 기반으로 다음 구성을 추가합니다.

spring:
 cloud:
   azure:
     active-directory:
       b2c:
         enabled: true
         base-uri: ${BASE_URI}             # Such as: https://xxxxb2c.b2clogin.com
         profile:
           tenant-id: <tenant>
         authorization-clients:
           ${RESOURCE_SERVER_A_NAME}:
             authorization-grant-type: client_credentials
             scopes: ${WEB_API_A_APP_ID_URL}/.default

참고 항목

허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 - ID 공급자의 사용자 계정이 테넌트에 존재하지 않는 잘못된 엔드포인트(개인 및 조직 계정) 사용 섹션을 참조하세요. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID에서 단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

Java 코드를 작성합니다 Webapp .

컨트롤러 코드의 경우 다음 예제를 참조할 수 있습니다.

class Demo {
   /**
    * Access to protected data from Webapp to WebApiA through client credential flow. The access token is obtained by webclient, or
    * <p>@RegisteredOAuth2AuthorizedClient("webApiA")</p>. In the end, these two approaches will be executed to
    * DefaultOAuth2AuthorizedClientManager#authorize method, get the access token.
    *
    * @return Respond to protected data from WebApi A.
    */
   @GetMapping("/webapp/webApiA")
   public String callWebApiA() {
       String body = webClient
           .get()
           .uri(LOCAL_WEB_API_A_SAMPLE_ENDPOINT)
           .attributes(clientRegistrationId("webApiA"))
           .retrieve()
           .bodyToMono(String.class)
           .block();
       LOGGER.info("Call callWebApiA(), request '/webApiA/sample' returned: {}", body);
       return "Request '/webApiA/sample'(WebApi A) returned a " + (body != null ? "success." : "failure.");
   }
}

보안 구성 코드는 웹 애플리케이션 액세스 시나리오와 동일합니다. 다음과 같이 다른 콩 webClient 을 추가합니다.

public class SampleConfiguration {
   @Bean
   public WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
       ServletOAuth2AuthorizedClientExchangeFilterFunction function =
           new ServletOAuth2AuthorizedClientExchangeFilterFunction(oAuth2AuthorizedClientManager);
       return WebClient.builder()
                       .apply(function.oauth2Configuration())
                       .build();
   }
}

Java 코드를 작성하려면 리소스 서버 액세스 섹션을 참조하세요WebApiA.

앱을 빌드하고 테스트합니다. WebappWebApiA 각각 포트 80808081에서 실행합니다. 및 WebApiA 애플리케이션을 Webapp 시작합니다. 성공적으로 로그인한 후 홈 페이지로 돌아갑니다. 그런 다음 리소스 응답을 얻기 WebApiA 위해 액세스할 http://localhost:8080/webapp/webApiA 수 있습니다.

사용량 3: 리소스 서버 액세스

이 시나리오는 로그인을 지원하지 않습니다. 액세스 토큰의 유효성을 검사하여 서버를 보호하고 유효한 경우 요청을 제공합니다.

사용 권한을 빌드하려면 사용량 2: 리소스 서버에 액세스하는 웹 애플리케이션을 참조하세요WebApiA.

권한을 추가하고 WebApiA 웹 애플리케이션에 대한 관리자 동의를 부여합니다.

pom.xml 파일에 다음 종속성을 추가합니다.

<dependencies>
   <dependency>
       <groupId>com.azure.spring</groupId>
       <artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
</dependencies>

다음 구성을 추가합니다.

spring:
 cloud:
   azure:
     active-directory:
       b2c:
         enabled: true
         base-uri: ${BASE_URI}             # Such as: https://xxxxb2c.b2clogin.com
         profile:
           tenant-id: <tenant>
         app-id-uri: ${APP_ID_URI}         # If you're using v1.0 token, configure app-id-uri for `aud` verification
         credential:
           client-id: ${AZURE_CLIENT_ID}           # If you're using v2.0 token, configure client-id for `aud` verification
         user-flows:
           sign-up-or-sign-in: ${SIGN_UP_OR_SIGN_IN_USER_FLOW_NAME}

참고 항목

허용되는 tenant-id 값은 , commonorganizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 - ID 공급자의 사용자 계정이 테넌트에 존재하지 않는 잘못된 엔드포인트(개인 및 조직 계정) 사용 섹션을 참조하세요. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID에서 단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

Java 코드를 작성합니다.

컨트롤러 코드의 경우 다음 예제를 참조할 수 있습니다.

class Demo {
   /**
    * webApiA resource api for web app
    * @return test content
    */
   @PreAuthorize("hasAuthority('APPROLE_WebApiA.SampleScope')")
   @GetMapping("/webApiA/sample")
   public String webApiASample() {
       LOGGER.info("Call webApiASample()");
       return "Request '/webApiA/sample'(WebApi A) returned successfully.";
   }
}

보안 구성 코드의 경우 다음 예제를 참조할 수 있습니다.

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
       http.authorizeRequests((requests) -> requests.anyRequest().authenticated())
           .oauth2ResourceServer()
           .jwt()
               .jwtAuthenticationConverter(new AadJwtBearerTokenAuthenticationConverter());
   }
}

앱을 빌드하고 테스트합니다. 포트 8081에서 실행합니다WebApiA. 리소스에 대한 액세스 토큰을 webApiA 가져오고 전달자 권한 부여 헤더로 액세스 http://localhost:8081/webApiA/sample 합니다.

사용량 4: 다른 리소스 서버에 액세스하는 리소스 서버

이 시나리오는 리소스 서버에 액세스하는 업그레이드이며 OAuth2 클라이언트 자격 증명 흐름에 따라 다른 애플리케이션 리소스에 대한 액세스를 지원합니다.

이전 단계를 참조하여 애플리케이션을 WebApiB 만들고 애플리케이션 권한을 WebApiB.SampleScope노출합니다.

{
   "allowedMemberTypes": [
       "Application"
   ],
   "description": "WebApiB.SampleScope",
   "displayName": "WebApiB.SampleScope",
   "id": "04989db0-3efe-4db6-b716-ae378517d2b7",
   "isEnabled": true,
   "lang": null,
   "origin": "Application",
   "value": "WebApiB.SampleScope"
}

Azure portal screenshot showing application WebApiB manifest screen with appRoles JSON highlighted.

권한에 대한 WebApiB 관리자 동의를 부여합니다.

Azure portal screenshot showing application WebApiA API permissions screen.

리소스 서버 액세스에 기초하여 pom.xml 파일에 다음 종속성을 추가합니다.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

리소스 서버 액세스 시나리오 구성을 기반으로 다음 구성을 추가합니다.

spring:
 cloud:
   azure:
     active-directory:
       b2c:
         enabled: true
         credential:
           client-secret: ${WEB_API_A_AZURE_CLIENT_SECRET}
         authorization-clients:
           ${RESOURCE_SERVER_B_NAME}:
             authorization-grant-type: client_credentials
             scopes: ${WEB_API_B_APP_ID_URL}/.default

Java 코드를 작성합니다.

컨트롤러 코드의 WebApiA 경우 다음 예제를 참조할 수 있습니다.

public class SampleController {
   /**
    * Access to protected data from WebApiA to WebApiB through client credential flow. The access token is obtained by webclient, or
    * <p>@RegisteredOAuth2AuthorizedClient("webApiA")</p>. In the end, these two approaches will be executed to
    * DefaultOAuth2AuthorizedClientManager#authorize method, get the access token.
    *
    * @return Respond to protected data from WebApi B.
    */
   @GetMapping("/webApiA/webApiB/sample")
   @PreAuthorize("hasAuthority('APPROLE_WebApiA.SampleScope')")
   public String callWebApiB() {
       String body = webClient
           .get()
           .uri(LOCAL_WEB_API_B_SAMPLE_ENDPOINT)
           .attributes(clientRegistrationId("webApiB"))
           .retrieve()
           .bodyToMono(String.class)
           .block();
       LOGGER.info("Call callWebApiB(), request '/webApiB/sample' returned: {}", body);
       return "Request 'webApiA/webApiB/sample'(WebApi A) returned a " + (body != null ? "success." : "failure.");
   }
}

컨트롤러 코드의 WebApiB 경우 다음 예제를 참조할 수 있습니다.

public class SampleController {
   /**
    * webApiB resource api for other web application
    * @return test content
    */
   @PreAuthorize("hasAuthority('APPROLE_WebApiB.SampleScope')")
   @GetMapping("/webApiB/sample")
   public String webApiBSample() {
       LOGGER.info("Call webApiBSample()");
       return "Request '/webApiB/sample'(WebApi B) returned successfully.";
   }
}

보안 구성 코드는 리소스 서버 액세스 시나리오와 동일하며, 다른 콩 webClient 은 다음과 같이 추가됩니다.

public class SampleConfiguration {
   @Bean
   public WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
       ServletOAuth2AuthorizedClientExchangeFilterFunction function =
           new ServletOAuth2AuthorizedClientExchangeFilterFunction(oAuth2AuthorizedClientManager);
       return WebClient.builder()
                       .apply(function.oauth2Configuration())
                       .build();
   }
}

앱을 빌드하고 테스트합니다. WebApiAWebApiB 각각 포트 80818082에서 실행합니다. 및 애플리케이션을 WebApiA 시작하고, 리소스에 대한 액세스 토큰을 webApiA 가져오고, 전달자 권한 부여 헤더로 액세스 http://localhost:8081/webApiA/webApiB/sampleWebApiB 합니다.

샘플

자세한 내용은 spring-cloud-azure-starter-active-directory-b2c 샘플을 참조 하세요.