Aggiungere l'accesso con Azure Active Directory B2C a un'app Web Spring
Questo articolo illustra come creare un'app Java con funzionalità di accesso usando Spring Initializr con Spring Boot Starter per Microsoft Entra ID.
In questa esercitazione apprenderai a:
- Creare un'applicazione Java con Spring Initializr
- Configurare Azure Active Directory B2C
- Proteggere l'applicazione con le classi e le annotazioni Spring Boot
- Compilare e testare l'applicazione Java
Microsoft Entra ID è la soluzione di gestione delle identità aziendali su scala cloud di Microsoft. Azure Active Directory B2C integra il set di funzionalità di Microsoft Entra ID, consentendo di gestire l'accesso di clienti, consumer e cittadini alle applicazioni business-to-consumer (B2C).
Prerequisiti
- Una sottoscrizione di Azure. Se non se ne ha già uno, creare un account gratuito prima di iniziare.
- Java Development Kit (JDK) supportato. Per altre informazioni sui JDK disponibili per l'uso durante lo sviluppo in Azure, vedere Supporto java in Azure e Azure Stack.
- Apache Maven, versione 3.0 o successiva.
Importante
Spring Boot versione 2.5 o successiva è necessario per completare i passaggi descritti in questo articolo.
Creare un'app con Spring Initializr
Passa a https://start.spring.io/.
Inserire i valori in base a queste istruzioni. Le etichette e il layout possono differire dall'immagine mostrata qui.
- In Progetto selezionare Progetto Maven.
- In Linguaggio selezionare Java.
- In Spring Boot selezionare 2.7.11.
- In Gruppo, Artefatto e Nome immettere lo stesso valore, usando una stringa descrittiva breve. L'interfaccia utente può compilare automaticamente alcuni di questi campi durante la digitazione.
- Nel riquadro Dipendenze selezionare Aggiungi dipendenze. Usare l'interfaccia utente per aggiungere dipendenze da Spring Web e Spring Security.
Nota
Spring Security 5.5.1, 5.4.7, 5.3.10 e 5.2.11 sono stati rilasciati per risolvere il seguente report CVE-2021-22119: Attacco Denial-of-Service con spring-security-oauth2-client. Se si usa la versione precedente, aggiornarla.
Selezionare Genera progetto e scaricare il progetto in un percorso nel computer locale. Spostare il file scaricato in una directory con lo stesso nome del progetto e decomprimerlo. Il layout del file avrà un aspetto simile al seguente, con il valore immesso per Gruppo al posto di
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
Creare e inizializzare un'istanza di Microsoft Entra
Creare l'istanza di Active Directory
Accedere a https://portal.azure.com.
Selezionare Crea una risorsa. Cercare Azure Active Directory B2C.
Seleziona Crea.
Selezionare Crea un nuovo tenant Azure AD B2C.
Specificare i valori appropriati per Nome organizzazione e Nome di dominio iniziale, quindi selezionare Crea.
Al termine della creazione di Active Directory, selezionare l'account nell'angolo in alto a destra, selezionare Cambia directory e quindi selezionare la directory creata. Si verrà reindirizzati alla home page del nuovo tenant.
b2c
Cercare quindi e selezionare Azure AD B2C.
Aggiungere una registrazione per l'app Spring Boot
Nel riquadro Gestisci selezionare Registrazioni app e quindi selezionare Nuova registrazione.
Nel campo Nome immettere il nome dell'app e quindi selezionare Registra.
Nel riquadro Gestisci selezionare Registrazioni app e quindi selezionare il nome dell'applicazione creato.
Selezionare Autenticazione, quindi Aggiungi una piattaforma e infine Web. Impostare gli URI di reindirizzamento su
http://localhost:8080/login/oauth2/code/
, quindi selezionare Configura.
Aggiungere segreti dell'app per l'app
Selezionare Certificati e segreti, quindi Nuovi segreti client. Immettere la descrizione del segreto e quindi selezionare Aggiungi. Dopo aver creato il segreto, selezionare l'icona di copia accanto al valore del segreto per copiare il valore da usare più avanti in questo articolo.
Nota
Se si lascia la sezione Certificati e segreti e si torna indietro, non sarà possibile visualizzare il valore del segreto. In tal caso, è necessario creare un altro segreto e copiarlo per un uso futuro. In alcuni casi, il valore del segreto generato può contenere caratteri problematici per l'inclusione nel file application.yml , ad esempio barra rovesciata o backtick. In tal caso, eliminare il segreto e generarne un altro.
Aggiungere il flusso utente
Passare alla pagina principale del tenant. Nella sezione Criteri del riquadro sinistro selezionare Flussi utente e quindi Nuovo flusso utente.
A questo punto si lascerà questa esercitazione, si eseguirà un'altra esercitazione e si tornerà a questa esercitazione al termine. Ecco alcuni aspetti da tenere presenti quando si passa all'altra esercitazione.
- Iniziare con il passaggio che richiede di selezionare Nuovo flusso utente.
- Quando questa esercitazione fa riferimento a
webapp1
, usare invece il valore immesso per Gruppo. - Quando si selezionano le attestazioni da restituire dai flussi, assicurarsi che sia selezionato Nome visualizzato. Senza questa attestazione, l'app compilata in questa esercitazione non funzionerà.
- Quando viene chiesto di eseguire i flussi utente, l'URL di reindirizzamento specificato in precedenza non è ancora attivo. È comunque possibile eseguire i flussi, ma il reindirizzamento non verrà completato correttamente. Si tratta di un comportamento previsto.
- Quando si raggiunge la sezione "Passaggi successivi", tornare in questa esercitazione.
Seguire tutti i passaggi descritti in Esercitazione: Creare flussi utente in Azure Active Directory B2C per creare flussi utente per l'iscrizione e l'accesso, la modifica del profilo e la reimpostazione della password.
Azure AD B2C supporta gli account locali e i provider di identità basati su social network. Per un esempio su come creare un provider di identità GitHub, vedere Configurare l'iscrizione e l'accesso con un account GitHub tramite Azure Active Directory B2C.
Configurare e compilare l'app
A questo punto, dopo aver creato l'istanza di Azure AD B2C e alcuni flussi utente, connettere l'app Spring all'istanza di Azure AD B2C.
Dalla riga di comando passare alla directory in cui è stato decompresso il file ZIP scaricato da Spring Initializr.
Passare alla cartella padre del progetto e aprire il file di progetto Maven pom.xml in un editor di testo.
Aggiungere le dipendenze per la sicurezza OAuth2 di Spring al file 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>
Per
spring-cloud-azure-starter-active-directory-b2c
, usare la versione più recente disponibile. Per cercarla, è possibile usare mvnrepository.com.Per
spring-boot-starter-thymeleaf
, usare la versione corrispondente alla versione di Spring Boot selezionata in precedenza, ad esempio2.3.4.RELEASE
.Per
thymeleaf-extras-springsecurity5
, usare la versione più recente disponibile. Per cercarla, è possibile usare mvnrepository.com. Al momento della stesura di questo articolo, l'ultima versione è3.0.4.RELEASE
.Salvare e chiudere il file pom.xml.
- Verificare che le dipendenze siano corrette eseguendo
mvn -DskipTests clean install
. Se non viene visualizzatoBUILD SUCCESS
, risolvere e risolvere il problema prima di continuare.
- Verificare che le dipendenze siano corrette eseguendo
Passare alla cartella src/main/resources del progetto e creare un file application.yml in un editor di testo.
Specificare le impostazioni per la registrazione dell'app usando i valori creati in precedenza, ad esempio:
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>
Si noti che il valore di
client-secret
è racchiuso tra virgolette singole. Ciò è necessario perché il valore di<secret-value>
conterrà quasi certamente alcuni caratteri che devono essere racchiusi tra virgolette singole quando sono presenti in YAML.Nota
Al momento della stesura di questo articolo, l'elenco completo dei valori di integrazione di Spring in Active Directory B2C disponibili per l'uso in application.yml è il seguente:
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:
Il file application.yml è disponibile nell'esempio spring-cloud-azure-starter-active-directory-b2c: aad-b2c-web-application su GitHub.
Salvare e chiudere il file application.yml.
Creare una cartella denominata controller in src/main/java/<yourGroupId>/<yourGroupId>, sostituendo
<yourGroupId>
con il valore immesso per Group.Creare un nuovo file Java denominato WebController.java nella cartella controller e aprirlo in un editor di testo.
Immettere il codice seguente, sostituendo
yourGroupId
nel modo appropriato, quindi salvare e chiudere il file: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"; } }
Poiché ogni metodo nel controller chiama
initializeModel()
e tale metodo chiamamodel.addAllAttributes(user.getAttributes());
, qualsiasi pagina HTML in src/main/resources/templates è in grado di accedere a uno di questi attributi, ad esempio${name}
,${grant_type}
o${auth_time}
. I valori restituiti dauser.getAttributes()
sono in effetti le attestazioni diid_token
per l'autenticazione. L'elenco completo delle attestazioni disponibili è elencato in Token ID di Microsoft Identity Platform.Creare una cartella denominata security in src/main/java/<yourGroupId>/<yourGroupId>, sostituendo
yourGroupId
con il valore immesso per Group.Creare un nuovo file Java denominato WebSecurityConfiguration.java nella cartella security e aprirlo in un editor di testo.
Immettere il codice seguente, sostituendo
yourGroupId
nel modo appropriato, quindi salvare e chiudere il file: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) ; } }
Copiare il file home.html dall'esempio spring-cloud-azure-starter-active-directory-b2c: aad-b2c-web-application in src/main/resources/templates e sostituire
${your-profile-edit-user-flow}
e${your-password-reset-user-flow}
con i nomi dei flussi utente creati in precedenza.
Compilare e testare l'app
Aprire un prompt dei comandi e cambiare la directory passando alla cartella in cui si trova il file pom.xml dell'app.
Compilare l'applicazione Spring Boot con Maven ed eseguirla, ad esempio:
Nota
È estremamente importante che l'orario secondo l'orologio di sistema in cui viene eseguita l'app Spring Boot locale sia accurato. Quando si usa OAuth 2.0, la tolleranza per lo sfasamento di orario è molto ridotta. Anche tre minuti di inesattezza possono causare l'esito negativo dell'accesso con un errore simile a
[invalid_id_token] An error occurred while attempting to decode the Jwt: Jwt used before 2020-05-19T18:52:10Z
. Al momento della stesura di questo articolo, time.gov include un indicatore della differenza tra il proprio orologio e l'orario effettivo. L'app è stata eseguita correttamente con uno sfasamento di + 0,019 secondi.mvn -DskipTests clean package mvn -DskipTests spring-boot:run
Al termine della compilazione e dell'avvio dell'applicazione tramite Maven, aprire
http://localhost:8080/
in un Web browser. Si dovrebbe essere reindirizzati alla pagina di accesso.Selezionare il collegamento con il testo relativo all'accesso. Si dovrebbe essere reindirizzati in Azure AD B2C per avviare il processo di autenticazione.
Dopo aver eseguito correttamente l'accesso, dovrebbe essere visualizzato l'esempio
home page
dal browser,
Risoluzione dei problemi
Le sezioni seguenti descrivono come risolvere alcuni problemi che potrebbero verificarsi.
Nome attributo mancante negli attributi
Durante l'esecuzione dell'esempio, è possibile che venga generata un'eccezione con il messaggio Missing attribute 'name' in attributes
. Il log per questa eccezione sarà simile all'output seguente:
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 viene visualizzato questo errore, controllare il flusso di lavoro utente creato in Esercitazione: Creare flussi utente in Azure Active Directory B2C. Quando si crea il flusso di lavoro dell'utente, per Attributi utente e attestazioni, assicurarsi di scegliere attributi e attestazioni per Nome visualizzato. Assicurarsi inoltre di configurare user-name-attribute-name
correttamente nel file di application.yml .
Accedere con cicli all'endpoint B2C
Questo problema è probabilmente dovuto a cookie inquinanti per localhost
. Pulire i cookie per localhost
e riprovare.
Riepilogo
In questa esercitazione si è creata una nuova applicazione Web Java con l'utilità di avvio per Azure Active Directory B2C, si è configurato un nuovo tenant di Azure AD B2C registrandovi quindi una nuova applicazione e infine si è configurata l'applicazione in modo da usare le annotazioni e le classi Spring per proteggere l'app Web.
Pulire le risorse
Quando le risorse create in questo articolo non sono più necessarie, usare il portale di Azure per eliminarle in modo da evitare addebiti imprevisti.
Passaggi successivi
Per altre informazioni su Spring e Azure, passare al centro di documentazione di Spring in Azure.