Adicionar login com o Azure Active Directory B2C a um aplicativo Spring Web
Este artigo mostra como criar um aplicativo Java com capacidade de autenticação usando o Spring Initializr com o Spring Boot Starter para o Microsoft Entra ID.
Neste tutorial, você aprenderá a:
- Criar um aplicativo 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 Java
o Microsoft Entra ID é a solução de identidade empresarial em escala de nuvem da Microsoft. Azure Active Directory B2C complementa o conjunto de recursos da ID do Microsoft Entra, permitindo que você gerencie o acesso de clientes, consumidores e cidadãos aos seus aplicativos B2C (entre empresas e consumidores).
Pré-requisitos
- Uma assinatura do Azure. Se você ainda não tiver uma, crie uma conta gratuita antes de começar.
- Um JDK (Java Development Kit) com suporte. Para obter mais informações sobre os JDKs disponíveis para uso ao desenvolver no Azure, consulte suporte a Java no Azure e no Azure Stack.
- Apache Maven, versão 3.0 ou superior.
Importante
O Spring Boot versão 2.5 ou superior é necessário para concluir as etapas neste artigo.
Criar um aplicativo usando o Spring Initializr
Navegue até https://start.spring.io/.
Preencha os valores de acordo com estas diretrizes. Os rótulos e o layout podem ser diferentes da imagem mostrada aqui.
- Em Projeto, selecione Projeto Maven.
- Em Language, selecione Java.
- Em Spring Boot, selecione 2.7.11.
- Em Group, Artifact e Name insira o mesmo valor usando uma cadeia de caracteres descritiva curta. A interface do usuário pode preencher automaticamente alguns desses campos conforme você digita.
- No painel Dependências, selecione Adicionar Dependências. Use a interface do usuário para adicionar dependências ao Spring Web e ao Spring Security.
Nota
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.
Selecione Gerar Projetoe então baixe o projeto para um caminho no computador local. Mova o arquivo baixado para um diretório com o nome do projeto e descompacte o arquivo. O layout do arquivo deve ser semelhante ao seguinte, com o valor que você inseriu 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
Faça logon em https://portal.azure.com.
Selecione Criar um recurso. Pesquise o Azure Active Directory B2C.
Selecione Criar.
Selecione Criar um novo Locatário Azure AD B2C.
Para Nome da organização e Nome de domínio inicial, forneça os valores apropriados e selecione Criar.
Quando a criação do Active Directory for concluída, selecione sua conta no canto superior direito, selecione de diretório do Switch e selecione o diretório criado. Você será redirecionado para a nova home page do locatário. Ou, então, procure
b2c
e selecione Azure AD B2C.
Adicionar um registro de aplicativo para seu aplicativo Spring Boot
No painel Gerenciar, selecione Registros de aplicativo e escolha Novo registro.
No campo Nome, insira o nome do aplicativo e selecione Registrar.
De volta ao painel Gerenciar, selecione Registros de Aplicativoe, em seguida, selecione o nome do aplicativo que você criou.
Selecione Autenticação, depois Adicionar uma plataforma, em seguida Web. Defina os URIs de Redirecionamento como
http://localhost:8080/login/oauth2/code/
e selecione Configurar.
Adicionar segredos do aplicativo para seu aplicativo
Selecione Certificados & segredos e Novos segredos do cliente. Insira sua descrição secreta e selecione Adicionar. Depois de criar o segredo, selecione o ícone de cópia ao lado do valor secreto para copiar o valor a ser usado posteriormente neste artigo.
Nota
Se você sair da seção Certificados & segredos e voltar, não poderá ver o valor do segredo. Nesse caso, você deve 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 fluxo de usuário
Navegue até 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.
Agora você deixará este tutorial, executará outro tutorial e voltará a este tutorial quando terminar. Aqui estão algumas coisas para ter em mente quando você vai para 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. - Quando você estiver selecionando declarações para retornar dos fluxos, verifique se Nome de Exibição está selecionado. Sem essa declaraçã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 no Tutorial: Criar fluxos de usuário no Azure Active Directory B2C para criar fluxos de usuário para "inscrever-se e entrar", "edição de perfil" e "redefinição de senha".
O Azure AD B2C dá suporte a contas locais, bem como a provedores de identidade social. Para obter um exemplo de criação de um provedor de identidade do GitHub, consulte 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 você criou a instância do Azure AD B2C e alguns fluxos de usuário, você conectará seu aplicativo Spring à instância do Azure AD B2C.
Na linha de comando, use o comando cd para mudar para o diretório onde você descompactou o arquivo .zip baixado do Spring Initializr.
Navegue até a pasta pai do projeto e abra o arquivo de projeto pom.xml Maven em um editor de texto.
Adicione as dependências de segurança do Spring OAuth2 ao 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 pesquisar isso.Para o
spring-boot-starter-thymeleaf
, use a versão correspondente à versão do Spring Boot selecionada 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 pesquisar isso. No momento da redação deste artigo, a versão mais recente era3.0.4.RELEASE
.Salve e feche o arquivo de pom.xml.
- Verifique se suas dependências estão corretas executando
mvn -DskipTests clean install
. Se você não verBUILD SUCCESS
, solucione o problema antes de continuar.
- Verifique se suas dependências estão corretas executando
Navegue até a pasta src/main/resources em seu projeto e crie um arquivo application.yml em um editor de texto.
Especifique as configurações para o 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
está entre aspas simples. Isso é necessário porque o valor de<secret-value>
certamente conterá alguns caracteres que exigem estar entre aspas únicas quando presentes no YAML.Nota
No momento, a lista completa de valores do Active Directory B2C Spring Integration que podem ser usados no application.yml é 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.
Salve e feche o arquivo application.yml.
Crie uma pasta chamada controlador em src/main/java/<yourGroupId>/<yourGroupId>, substituindo
<yourGroupId>
pelo valor que você inseriu para Grupo.Crie um novo arquivo Java chamado
WebController.java na pasta do controladore abra-o em um editor de texto. Insira o código a seguir, alterando
yourGroupId
adequadamente e, em seguida, 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 chamamodel.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 deuser.getAttributes()
são, de fato, as declarações doid_token
para a autenticação. A lista completa de declarações disponíveis está listada em tokens de ID da plataforma Microsoft Identity.Crie uma pasta chamada segurança em src/main/java/<yourGroupId>/<yourGroupId>, substituindo
yourGroupId
pelo valor que você inseriu para Grupo.Crie um novo arquivo Java chamado
WebSecurityConfiguration.java na pasta de segurança doe abra-o em um editor de texto. Insira o código a seguir, alterando
yourGroupId
adequadamente e, em seguida, 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) ; } }
Copie o arquivo home.html do exemplo spring-cloud-azure-starter-active-directory-b2c: aad-b2c-web-application para src/main/resources/templatese substitua os
${your-profile-edit-user-flow}
e${your-password-reset-user-flow}
pelos nomes dos fluxos de usuário que você criou anteriormente.
Compilar e testar seu aplicativo
Abra um prompt de comando e altere o diretório para a pasta em que o arquivo pom.xml do aplicativo está localizado.
Crie seu aplicativo Spring Boot com o Maven e execute-o; por exemplo:
Nota
É 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 à 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
Depois que o aplicativo for criado e iniciado pelo Maven, abra
http://localhost:8080/
em um navegador da Web; você deve ser redirecionado para a página de logon.Selecione o link com o texto relacionado a fazer login. Você deve ser redirecionado ao Azure AD B2C para iniciar o processo de autenticação.
Depois de fazer login com êxito, você deverá ver o exemplo
home page
no navegador.
Solução de problemas
As seções a seguir descrevem como resolver alguns problemas que você pode encontrar.
Nome do atributo ausente na lista de atributos
Ao executar o exemplo, você pode obter 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 novamente o fluxo de trabalho do usuário criado no Tutorial : Criar fluxos de 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, certifique-se de configurar corretamente user-name-attribute-name
no arquivo application.yml.
Entrar com loops no ponto de extremidade B2C
Esse problema provavelmente ocorre devido a cookies poluídos para localhost
. Limpe os cookies do localhost
e tente novamente.
Resumo
Neste tutorial, você criou um novo aplicativo Java para a web usando o modelo inicial do Azure Active Directory B2C, configurou um novo locatário do Azure AD B2C, registrou um novo aplicativo nesse locatário e então configurou o seu aplicativo para utilizar anotações e classes do Spring a fim de proteger o aplicativo web.
Limpar recursos
Quando não for mais necessário, use o portal do Azure para excluir os recursos criados neste artigo e evitar encargos inesperados.
Próximas etapas
Para saber mais sobre o Spring e o Azure, prossiga para o centro de documentação do Spring on Azure.