Incorporación de inicio de sesión con Azure Active Directory B2C a una aplicación web de Spring
En este artículo se muestra cómo crear una aplicación de Java con la funcionalidad de inicio de sesión mediante Spring Initializr con spring Boot Starter para el id. de Microsoft Entra.
En este tutorial, aprenderá a:
- Crear una aplicación de Java mediante Spring Initializr
- Configurar Azure Active Directory B2C
- Proteger la aplicación con las clases y anotaciones de Spring Boot
- Compilar y probar la aplicación de Java
Microsoft Entra ID es la solución de identidad empresarial de escala de nube de Microsoft. Azure Active Directory B2C complementa el conjunto de características de Microsoft Entra ID, lo que le permite administrar el acceso de cliente, consumidor y ciudadano a las aplicaciones de negocio a consumidor (B2C).
Requisitos previos
- Suscripción a Azure. Si aún no tiene una, cree una cuenta gratuita antes de empezar.
- Un kit de desarrollo de Java (JDK) admitido Para más información sobre los JDK disponibles para desarrollar en Azure, consulte Compatibilidad con Java en Azure y Azure Stack.
- Apache Maven, versión 3.0 o posterior.
Importante
Se requiere Spring Boot versión 2.5 o posterior para completar los pasos descritos en este artículo.
Creación de una aplicación con Spring Initialzr
Vaya a https://start.spring.io/.
Rellene los valores de acuerdo con esta guía. Las etiquetas y el diseño pueden diferir de la imagen que se muestra aquí.
- En Proyecto, seleccione Proyecto de Maven.
- En Lenguaje, seleccione Java.
- En Spring Boot, seleccione 2.7.11.
- En Grupo, Artefacto y Nombre, escriba el mismo valor usando una cadena descriptiva breve. La interfaz de usuario puede rellenar automáticamente algunos de estos campos a medida que escribe.
- En el panel Dependencias, seleccione Agregar dependencias. Use la interfaz de usuario para agregar dependencias en Spring Web y Spring Security.
Nota:
Las versiones 5.5.1, 5.4.7, 5.3.10 y 5.2.11 de Spring Security se han publicado para abordar el siguiente informe CVE CVE-2021-22119: ataque por denegación de servicio con spring-security-oauth2-client. Si usa la versión anterior, actualícela.
Seleccione Generar proyecto y descargue el proyecto en una ruta de acceso del equipo local. Mueva el archivo descargado a un directorio que se llame como el proyecto y descomprima el archivo. El diseño del archivo tendrá un aspecto similar al siguiente, con el valor especificado para Grupo en 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
Creación e inicialización de una instancia de Microsoft Entra
Creación de la instancia de Active Directory
Inicie sesión en https://portal.azure.com.
Seleccione Crear un recurso. Busque Azure Active Directory B2C.
Seleccione Crear.
Seleccione Crear un nuevo inquilino de Azure AD B2C.
En Nombre de la organización y Nombre de dominio inicial, proporcione los valores correspondientes y, a continuación, seleccione Crear.
Una vez completada la creación de Active Directory, seleccione la cuenta en la esquina superior derecha, seleccione Cambiar directorio y, a continuación, seleccione el directorio creado. Se le redirigirá a la nueva página principal del inquilino. Después, busque
b2c
y seleccione Azure AD B2C.
Adición de un registro de aplicación para la aplicación de Spring Boot
En el panel Administrar, seleccione Registros de aplicaciones y, a continuación, seleccione Nuevo registro.
En el campo Nombre, escriba el nombre de la aplicación y seleccione Registrar.
De nuevo en el panel Administrar, seleccione Registros de aplicaciones y, a continuación, seleccione el nombre de la aplicación que ha creado.
Seleccione Autenticación y, a continuación, Agregar una plataforma y, después, Web. Establezca los URI de redireccionamiento en
http://localhost:8080/login/oauth2/code/
y, a continuación, seleccione Configurar.
Adición de secretos de aplicación para la aplicación
Seleccione Certificados y secretos y, después, Nuevos secretos de cliente. Introduzca la descripción del secreto y, a continuación, seleccione Agregar. Después de crear el secreto, seleccione el icono de copia junto al valor del secreto para copiarlo y usarlo más adelante en este artículo.
Nota:
Si deja la sección Certificados y secretos y vuelve, no podrá ver el valor del secreto. En ese caso, debe crear otro secreto y copiarlo para usarlo más adelante. Algunas veces, el valor del secreto generado puede contener caracteres que son problemáticos para su inclusión en el archivo application.yml, como la barra diagonal inversa o el acento grave. En ese caso, descarte ese secreto y genere otro.
Incorporación de flujo de usuario
Vaya a la página principal del inquilino. En la sección Directivas del panel izquierdo, seleccione Flujos de usuario y, después, Nuevo flujo de usuario.
Ahora dejará este tutorial, ejecutará otro tutorial y volverá a este tutorial cuando haya terminado. Estos son algunos aspectos que hay que tener en cuenta cuando visite el otro tutorial.
- Comience en el paso que le pide que seleccione Nuevo flujo de usuario.
- Cuando este tutorial haga referencia a
webapp1
, use en su lugar el valor que especificó para Grupo. - Al seleccionar las notificaciones que se van a devolver de los flujos, asegúrese de que se selecciona Nombre para mostrar. Sin esta notificación, la aplicación que se compila en este tutorial no funcionará.
- Cuando se le pide que ejecute los flujos de usuario, la dirección URL de redireccionamiento que especificó anteriormente aún no está activa. Todavía puede ejecutar los flujos, pero el redireccionamiento no se completará correctamente. Se espera que esto sea así.
- Cuando llegue a "Pasos siguientes", vuelva a este tutorial.
Siga todos los pasos descritos en Tutorial: Creación de flujos de usuario en Azure Active Directory B2C para crear flujos de usuario para "registro e inicio de sesión", "edición de perfiles" y "restablecimiento de contraseña".
Azure AD B2C admite cuentas locales, así como proveedores de identidades sociales. Para ver un ejemplo de cómo crear un proveedor de identidades de GitHub, consulte Configuración de la suscripción y del inicio de sesión con una cuenta de GitHub mediante Azure Active Directory B2C.
Configuración y compilación de la aplicación
Ahora que ha creado la instancia de Azure AD B2C y algunos flujos de usuario, conectará la aplicación de Spring a la instancia de Azure AD B2C.
Desde la línea de comandos, vaya al directorio donde descomprimió el archivo ZIP que descargó de Spring Initializr.
Vaya a la carpeta principal del proyecto y abra el archivo del proyecto de Maven pom.xml en un editor de texto.
Agregue las dependencias para la seguridad OAuth2 de Spring 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
spring-cloud-azure-starter-active-directory-b2c
, actualice a la versión más reciente disponible. Es posible que pueda usar mvnrepository.com para consultarla.Para
spring-boot-starter-thymeleaf
, use la versión correspondiente a la versión de Spring Boot seleccionada anteriormente, por ejemplo2.3.4.RELEASE
.Para
thymeleaf-extras-springsecurity5
, use la versión más reciente disponible. Es posible que pueda usar mvnrepository.com para consultarla. En el momento de escribir este artículo, la versión más reciente es3.0.4.RELEASE
.Guarde y cierre el archivo pom.xml.
- Para comprobar si las dependencias son correctas, ejecute
mvn -DskipTests clean install
. Si no veBUILD SUCCESS
, solucione y resuelva el problema antes de continuar.
- Para comprobar si las dependencias son correctas, ejecute
Vaya a la carpeta src/main/resources del proyecto y cree un archivo application.yml en un editor de texto.
Especifique la configuración del registro de su aplicación con los valores que creó anteriormente; por ejemplo:
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 el valor
client-secret
está entre comillas simples. Esto es necesario porque el valor de<secret-value>
seguramente contendrá algunos caracteres que tienen que estar entre comillas simples cuando están presentes en YAML.Nota:
En el momento de escribir este artículo, la lista completa de valores de integración de Azure Directory Spring B2C que están disponibles para usar en application.yml es la siguiente:
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:
El archivo application.yml está disponible en spring-cloud-azure-starter-active-directory-b2c sample: aad-b2c-web-application en GitHub.
Guarde y cierre el archivo application.yml.
Cree una carpeta denominada controller en src/main/java/<yourGroupId>/<yourGroupId>, reemplazando por
<yourGroupId>
el valor especificado para Group.Cree un archivo de Java nuevo llamado WebController.java en la carpeta controller y ábralo en un editor de texto.
Escriba el código siguiente, cambiando
yourGroupId
al valor que corresponda y, a continuación, guarde y cierre el archivo: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 todos los métodos del controlador llaman a
initializeModel()
, y ese método llama amodel.addAllAttributes(user.getAttributes());
, cualquier página HTML en src/main/resources/templates puede tener acceso a cualquiera de esos atributos, como${name}
,${grant_type}
o${auth_time}
. De hecho, los valores devueltos poruser.getAttributes()
son las notificaciones deid_token
para la autenticación. La lista completa de notificaciones disponibles se muestra en Tokens de identificador de la plataforma de identidad de Microsoft.Cree una carpeta denominada security en src/main/java/<yourGroupId/<yourGroupId>>, reemplazando por
yourGroupId
el valor especificado para Group.Cree un archivo Java nuevo llamado WebSecurityConfiguration.java en la carpeta security y ábralo en un editor de texto.
Escriba el código siguiente, cambiando
yourGroupId
al valor que corresponda y, a continuación, guarde y cierre el archivo: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 el archivo home.html del ejemplo spring-cloud-azure-starter-active-directory-b2c: aad-b2c-web-application en src/main/resources/templates y reemplace y
${your-profile-edit-user-flow}
${your-password-reset-user-flow}
por los nombres de los flujos de usuario que creó anteriormente.
Compilación y prueba de la aplicación
Abra un símbolo del sistema y cambie el directorio a la carpeta donde se encuentra el archivo pom.xml de su aplicación.
Compile la aplicación de Spring Boot con Maven y ejecútela; por ejemplo:
Nota:
Es muy importante que la hora según el reloj del sistema en el que se ejecuta la aplicación de Spring Boot local sea preciso. Hay muy poca tolerancia a la desviación del reloj cuando se usa OAuth 2.0. Incluso tres minutos de inexactitud pueden provocar un error en el inicio de sesión con un error similar a
[invalid_id_token] An error occurred while attempting to decode the Jwt: Jwt used before 2020-05-19T18:52:10Z
. En el momento de redactar este documento, time.gov indica la diferencia de su reloj respecto de la hora real. La aplicación se ejecutó correctamente con una desviación de +0,019 segundos.mvn -DskipTests clean package mvn -DskipTests spring-boot:run
Después de que Maven compile e inicie la aplicación, abra
http://localhost:8080/
en un explorador web; se le redirigirá a la página de inicio de sesión.Seleccione el vínculo que tenga el texto relacionado con el inicio de sesión. Se le redirigirá a Azure AD B2C para iniciar el proceso de autenticación.
Una vez que haya iniciado sesión correctamente, debería ver el ejemplo
home page
desde el explorador.
Solución de problemas
En las secciones siguientes se describe cómo resolver algunos problemas que pueden surgir.
Falta el nombre de los atributos
Al ejecutar el ejemplo, puede aparecer una excepción con el mensaje Missing attribute 'name' in attributes
. El registro de esta excepción tendrá un aspecto similar al de la salida siguiente:
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]
Si recibe este error, compruebe de nuevo el flujo de trabajo de usuario que creó en Tutorial: Creación de flujos de usuario en Azure Active Directory B2C. Cuando cree el flujo de trabajo de usuario, en Atributos y notificaciones de usuario, asegúrese de elegir atributos y notificaciones en Nombre para mostrar. Además, asegúrese de configurar correctamente user-name-attribute-name
en el archivo application.yml.
Inicio de sesión con bucles en el punto de conexión de B2C
Este problema es más probable que se deba a cookies contaminadas de localhost
. Limpie las cookies de localhost
e inténtelo de nuevo.
Resumen
En este tutorial, ha creado una nueva aplicación web de Java mediante el iniciador de Azure Active Directory B2C, ha configurado un nuevo inquilino de Azure AD B2C y ha registrado una nueva aplicación en él; después, ha configurado la aplicación para que use las clases y anotaciones de Spring para proteger la aplicación web.
Limpieza de recursos
Cuando ya no lo necesite, use Azure Portal para eliminar los recursos creados en este artículo y evitar cargos inesperados.
Pasos siguientes
Para más información acerca de Spring y Azure, vaya al centro de documentación de Azure.