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

Importante

Spring Boot versione 2.5 o successiva è necessario per completare i passaggi descritti in questo articolo.

Creare un'app con Spring Initializr

  1. Passa a https://start.spring.io/.

  2. 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.

  3. 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

  1. Accedere a https://portal.azure.com.

  2. Selezionare Crea una risorsa. Cercare Azure Active Directory B2C.

    Creare una nuova istanza di Azure Active Directory B2C usando il portale di Azure.

  3. Seleziona Crea.

    Voce di Azure Marketplace per Azure Active Directory B2C.

  4. Selezionare Crea un nuovo tenant Azure AD B2C.

    portale di Azure opzione per creare un nuovo tenant di Azure AD B2C.

  5. Specificare i valori appropriati per Nome organizzazione e Nome di dominio iniziale, quindi selezionare Crea.

    Schermata Crea tenant di Azure AD B2C.

  6. 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.

    Individuare il servizio Azure AD B2C.

Aggiungere una registrazione per l'app Spring Boot

  1. Nel riquadro Gestisci selezionare Registrazioni app e quindi selezionare Nuova registrazione.

    Screenshot della portale di Azure che mostra la schermata di Registrazioni app di Azure AD B2C.

  2. Nel campo Nome immettere il nome dell'app e quindi selezionare Registra.

    Registrare un modulo dell'applicazione in Azure AD B2C.

  3. Nel riquadro Gestisci selezionare Registrazioni app e quindi selezionare il nome dell'applicazione creato.

    Registrazioni app schermata con il nome visualizzato selezionato.

  4. Selezionare Autenticazione, quindi Aggiungi una piattaforma e infine Web. Impostare gli URI di reindirizzamento su http://localhost:8080/login/oauth2/code/, quindi selezionare Configura.

    Opzioni selezionate per l'autenticazione, aggiungere una piattaforma Web.

    Configurare la schermata Web con il campo URI di reindirizzamento selezionato.

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.

Aggiungere una schermata del segreto client.

Schermata Certificati e segreti con il pulsante Copia selezionato.

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

  1. Passare alla pagina principale del tenant. Nella sezione Criteri del riquadro sinistro selezionare Flussi utente e quindi Nuovo flusso utente.

  2. 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.

  1. Dalla riga di comando passare alla directory in cui è stato decompresso il file ZIP scaricato da Spring Initializr.

  2. Passare alla cartella padre del progetto e aprire il file di progetto Maven pom.xml in un editor di testo.

  3. 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 esempio 2.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.

  4. Salvare e chiudere il file pom.xml.

    • Verificare che le dipendenze siano corrette eseguendo mvn -DskipTests clean install. Se non viene visualizzato BUILD SUCCESS, risolvere e risolvere il problema prima di continuare.
  5. Passare alla cartella src/main/resources del progetto e creare un file application.yml in un editor di testo.

  6. 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.

  7. Salvare e chiudere il file application.yml.

  8. Creare una cartella denominata controller in src/main/java/<yourGroupId>/<yourGroupId>, sostituendo <yourGroupId> con il valore immesso per Group.

  9. Creare un nuovo file Java denominato WebController.java nella cartella controller e aprirlo in un editor di testo.

  10. 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 chiama model.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 da user.getAttributes() sono in effetti le attestazioni di id_token per l'autenticazione. L'elenco completo delle attestazioni disponibili è elencato in Token ID di Microsoft Identity Platform.

  11. Creare una cartella denominata security in src/main/java/<yourGroupId>/<yourGroupId>, sostituendo yourGroupId con il valore immesso per Group.

  12. Creare un nuovo file Java denominato WebSecurityConfiguration.java nella cartella security e aprirlo in un editor di testo.

  13. 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)
            ;
        }
    }
    
  14. 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

  1. Aprire un prompt dei comandi e cambiare la directory passando alla cartella in cui si trova il file pom.xml dell'app.

  2. 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
    
  3. 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.

    Pagina di accesso dell'app Web.

  4. Selezionare il collegamento con il testo relativo all'accesso. Si dovrebbe essere reindirizzati in Azure AD B2C per avviare il processo di autenticazione.

  5. Dopo aver eseguito correttamente l'accesso, dovrebbe essere visualizzato l'esempio home page dal browser,

    Accesso riuscito dell'app Web.

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.