Adicionar entrada com o Azure Active Directory B2C a um aplicativo Web Spring

Este artigo mostra como criar um aplicativo Java com capacidade de entrada usando o Spring Initializr com o Spring Boot Starter para Microsoft Entra ID.

Neste tutorial, você aprenderá a:

  • Criar um aplicativo do Java usando o Spring Initializr
  • Configurar o Azure Active Directory B2C
  • Proteger o aplicativo com classes e anotações do Spring Boot
  • Compilar e testar seu aplicativo do Java

O Microsoft Entra ID é a solução de identidade corporativa em escala de nuvem da Microsoft. O Azure Active Directory B2C complementa o conjunto de recursos do Microsoft Entra ID, permitindo que você gerencie o acesso de clientes, consumidores e cidadãos aos seus aplicativos B2C (business-to-consumer).

Pré-requisitos

Importante

O Spring Boot versão 2.5 ou superior é necessário para concluir as etapas deste artigo.

Criar um aplicativo usando o Spring Initialzr

  1. Navegue até https://start.spring.io/.

  2. Preencha os valores de acordo com essas diretrizes. Os rótulos e o layout podem ser diferentes da imagem mostrada aqui.

    • Em Projeto, selecione Projeto Maven.
    • Em Linguagem de programação, selecione Java.
    • Em Spring Boot, selecione 2.7.11.
    • Em Grupo, Artefato e Nome, insira o mesmo valor, usando uma cadeia de caracteres curta descritiva. A interface do usuário pode preencher automaticamente alguns desses campos à medida que você digita.
    • No painel Dependências, selecione Adicionar Dependências. Use a interface do usuário para adicionar dependências ao Spring Web e à Segurança do Spring.

    Observação

    O Spring Security 5.5.1, 5.4.7, 5.3.10 e 5.2.11 foi lançado em resposta ao relatório CVE-2021-22119: ataque de negação de serviço com spring-security-oauth2-client. Se você estiver usando a versão mais antiga, atualize-a.

  3. Selecione Gerar Projeto e baixe o projeto para um caminho no seu computador local. Mova o arquivo baixado para um diretório chamado após o projeto e descompacte o arquivo. O layout do arquivo deve ser semelhante ao exibido a seguir, com o valor inserido para Grupo no lugar de 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
    

Criar e inicializar uma instância do Microsoft Entra

Criar a instância do Active Directory

  1. Faça logon em https://portal.azure.com.

  2. Selecione Criar um recurso. Pesquise o Azure Active Directory B2C.

    Crie uma instância do Azure Active Directory B2C usando o portal do Azure.

  3. Selecione Criar.

    Entrada do Azure Marketplace para o Azure Active Directory B2C.

  4. Selecione Criar um novo Locatário Azure AD B2C.

    Opção do portal do Azure para criar um locatário do Azure AD B2C.

  5. Para Nome da organização e Nome de domínio inicial, forneça os valores apropriados e selecione Criar.

    Tela Criar Locatário do Azure AD B2C.

  6. Quando a criação do Active Directory estiver concluída, selecione sua conta no canto superior direito, selecione Alternar diretório e selecione o diretório criado. Você será redirecionado para a página inicial do novo locatário. Ou, então, procure b2c e selecione Azure AD B2C.

    Localize o serviço do Azure AD B2C.

Adicionar um registro de aplicativo para seu aplicativo do Spring Boot

  1. No painel Gerenciar, selecione Registros de aplicativo e, em seguida, selecione Novo registro.

    Captura de tela do portal do Azure mostrando a tela Registros de aplicativo do Azure AD B2C.

  2. No campo Nome, insira o nome do aplicativo e selecione Registrar.

    Registro de um formulário de aplicativo do Azure AD B2C.

  3. De volta ao painel Gerenciar, selecione Registros de aplicativo e escolha o nome do aplicativo criado.

    Tela de Registros de aplicativo com o nome de exibição selecionado.

  4. Selecione Autenticação, Adicionar uma plataforma e Web. Defina os URIs de Redirecionamento como http://localhost:8080/login/oauth2/code/ e selecione Configurar.

    Opções selecionadas para autenticação: Adicionar uma plataforma e Web.

    Tela Configurar a Web com o campo URIs de Redirecionamento selecionado.

Adicionar segredos do aplicativo para seu aplicativo

Em Certificados e segredos, selecione Novos segredos do cliente. Insira sua descrição de segredo e selecione Adicionar. Depois de criar o segredo, escolha o ícone de cópia ao lado do valor do segredo para copiar o valor para uso posterior neste artigo.

Tela de Adicionar um segredo do cliente.

Tela de Certificados e segredos com o botão Copiar selecionado.

Observação

Se você sair da seção Certificados e segredos e voltar, não poderá ver o valor secreto. Nesse caso, precisará criar outro segredo e copiá-lo para uso futuro. Ocasionalmente, o valor do segredo gerado pode conter caracteres problemáticos para inclusão no arquivo application.yml, como barra invertida ou acento grave. Nesse caso, descarte esse segredo e gere outro.

Adicionar um fluxo do usuário

  1. Acesse a página principal do locatário. Na seção Políticas do painel esquerdo, selecione Fluxos dos Usuários e escolha Novo fluxo de usuário.

  2. Agora você deixará este tutorial, executará outro tutorial e voltará a este tutorial quando terminar. Aqui estão algumas coisas para se ter em mente quando você acessar o outro tutorial.

    • Comece com a etapa que solicita que você selecione Novo fluxo de usuário.
    • Quando este tutorial se refere a webapp1, use o valor inserido para Grupo.
    • Ao selecionar declarações para retornar dos fluxos, verifique se Nome para Exibição está selecionado. Sem essa afirmação, o aplicativo que está sendo criado neste tutorial não funcionará.
    • Quando você é solicitado a executar os fluxos de usuário, a URL de redirecionamento especificada anteriormente ainda não está ativa. Você ainda pode executar os fluxos, mas o redirecionamento não será concluído com êxito. Isso é esperado.
    • Quando você chegar a "Próximas etapas", retorne a este tutorial.

    Siga todas as etapas em Tutorial: Criar fluxos de usuário no Azure Active Directory B2C para criar fluxos de usuário para "inscrição e entrada", "edição de perfil" e "redefinição de senha".

    O Azure AD B2C é compatível com contas locais, bem como com provedores de identidade social. Para obter um exemplo de como criar um provedor de identidade do GitHub, confira Configurar a inscrição e a entrada com uma conta do GitHub usando o Azure Active Directory B2C.

Configurar e compilar seu aplicativo

Agora que criou a instância do Azure AD B2C e alguns fluxos dos usuários, você conectará seu aplicativo Spring à instância do Azure AD B2C.

  1. Na linha de comando, execute cd para o diretório em que você descompactou o arquivo .zip baixado do Spring Initializr.

  2. Navegue até a pasta pai no projeto e abra o arquivo de projeto Maven pom.xml em um editor de texto.

  3. Adicione as dependências de segurança do Spring OAuth2 a 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>
    

    Para o spring-cloud-azure-starter-active-directory-b2c, use a versão mais recente disponível. Talvez você possa usar mvnrepository.com para procurar isso.

    Para o spring-boot-starter-thymeleaf, use a versão correspondente à versão do Spring Boot que você selecionou acima, por exemplo 2.3.4.RELEASE.

    Para thymeleaf-extras-springsecurity5, use a versão mais recente disponível. Talvez você possa usar mvnrepository.com para procurar isso. No momento da redação deste artigo, a versão mais recente era 3.0.4.RELEASE.

  4. Salve e feche o arquivo pom.xml.

    • Verifique se suas dependências estão corretas executando mvn -DskipTests clean install. Se você não vir BUILD SUCCESS, solucione e resolva o problema antes de continuar.
  5. Navegue até a pasta src/main/resources no seu projeto e crie um arquivo application.yml em um editor de texto.

  6. Especifique as configurações de registro do aplicativo usando os valores criados anteriormente. Por exemplo:

    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> 
    

    Observe que o valor client-secret é colocado entre aspas simples. Isso é necessário porque o valor de <secret-value> certamente conterá alguns caracteres que precisam estar entre aspas simples quando presentes no YAML.

    Observação

    No momento da redação deste artigo, a lista completa dos valores de Integração do Spring do Active Directory B2C disponíveis para uso no application.yml era a seguinte:

    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:
    

    O arquivo application.yml está disponível no exemplo spring-cloud-azure-starter-active-directory-b2c: aad-b2c-web-application no GitHub.

  7. Salve e feche o arquivo application.yml.

  8. Crie uma pasta chamada controller em src/main/java/<yourGroupId>/yourGroupId>,< substituindo <yourGroupId> pelo valor inserido para Group.

  9. Crie um arquivo Java chamado WebController.java na pasta controlador e abra-o em um editor de texto.

  10. Insira o seguinte código, alterando yourGroupId adequadamente e salve e feche o arquivo:

    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";
        }
    }
    

    Como cada método no controlador chama initializeModel() e esse método chama model.addAllAttributes(user.getAttributes());, qualquer página HTML em src/main/resources/templates é capaz de acessar qualquer um desses atributos, como ${name}, ${grant_type} ou ${auth_time}. Os valores retornados de user.getAttributes() são, de fato, as declarações do id_token para a autenticação. A lista completa de declarações disponíveis está listada em tokens de ID da plataforma Microsoft Identity.

  11. Crie uma pasta chamada security em src/main/java/<yourGroupId/<yourGroupId>>, substituindo yourGroupId pelo valor inserido para Group.

  12. Crie um arquivo Java chamado WebSecurityConfiguration.java na pasta segurança e abra-o em um editor de texto.

  13. Insira o seguinte código, alterando yourGroupId adequadamente e salve e feche o arquivo:

    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. Copie o arquivo home.html do exemplo spring-cloud-azure-starter-active-directory-b2c : aad-b2c-web-application para src/main/resources/templates e substitua o ${your-profile-edit-user-flow} e ${your-password-reset-user-flow} pelos nomes dos fluxos de usuário criados anteriormente.

Crie e testar seu aplicativo

  1. Abra um prompt de comando e altere o diretório para a pasta em que seu arquivo pom.xml do aplicativo está localizado.

  2. Crie seu aplicativo Spring Boot com Maven e execute-o; por exemplo:

    Observação

    É extremamente importante que o tempo seja preciso de acordo com o relógio do sistema em que o aplicativo Spring Boot local é executado. Há muito pouca tolerância de distorção do relógio ao usar o OAuth 2.0. Até três minutos de imprecisão pode fazer com que a entrada falhe com um erro semelhante a [invalid_id_token] An error occurred while attempting to decode the Jwt: Jwt used before 2020-05-19T18:52:10Z. No momento da redação deste artigo, time.gov tinha um indicador que mostrava o valor da diferença entre o seu relógio e a hora real. O aplicativo foi executado com êxito com uma distorção de +0,019 segundos.

    mvn -DskipTests clean package
    mvn -DskipTests spring-boot:run
    
  3. Após a criação e inicialização de seu aplicativo pelo Maven, abra http://localhost:8080/ em um navegador da Web; você deverá ser redirecionado para a página de logon.

    Página de logon do aplicativo Web.

  4. Selecione o link com o texto relacionado à entrada. Você deve ser redirecionado do Azure AD B2C para iniciar o processo de autenticação.

  5. Depois de fazer login com êxito, você verá o exemplo home page do navegador,

    Logon bem-sucedido do aplicativo Web.

Solução de problemas

As seções a seguir descrevem como resolver alguns problemas que você poderá enfrentar.

Nome de atributo ausente em atributos

Ao executar o exemplo, você pode receber uma exceção com a mensagem Missing attribute 'name' in attributes. O log dessa exceção será semelhante à seguinte saída:

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]

Se você receber esse erro, verifique o fluxo de trabalho do usuário criado no Tutorial: Criar fluxos do usuário no Azure Active Directory B2C. Ao criar o fluxo de trabalho do usuário, em Atributos de usuário e declarações, escolha atributos e declarações no Nome de Exibição. Além disso, configure user-name-attribute-name corretamente no arquivo application.yml.

Entrar com loops no ponto de extremidade B2C

Esse problema ocorre mais provavelmente devido a cookies poluídos de localhost. Limpe os cookies de localhost e tente novamente.

Resumo

Neste tutorial, você criou um aplicativo Web do Java usando o iniciador do Azure Active Directory B2C, configurou um novo locatário do Azure AD B2C e registrou um novo aplicativo. Em seguida, configurou o aplicativo para usar as classes e as anotações do Spring para proteger o aplicativo Web.

Limpar os recursos

Quando não for mais necessário, use o portal do Azure para excluir os recursos criados neste artigo para evitar cobranças inesperadas.

Próximas etapas

Para saber mais sobre o Spring e o Azure, continue no Spring no Centro de Documentação do Azure.