Esercizio - Consentire l'accesso degli utenti con MSAL

Completato

In questo esercizio si userà Microsoft Authentication Library per Java (MSAL4J) per aggiungere l'autenticazione in un'applicazione Web Java di esempio e consentire agli utenti di accedere con gli account Microsoft Entra.

L'applicazione di esempio che verrà descritta in questo esercizio è un'applicazione servlet Java che consente agli utenti di accedere e visualizzare il nome utente e le informazioni di base del profilo. Consente anche di chiamare l'API Microsoft Graph per visualizzare alcune informazioni sull'utente.

Creazione di un'applicazione Web Java

Dalla shell o della riga di comando:

  1. Creare una cartella per l'applicazione.

    mkdir ~/javawebapp
    
  2. Clonare l'applicazione di esempio dal repository GitHub alla nuova cartella.

    git clone https://github.com/Azure-Samples/ms-identity-java-servlet-webapp-authentication.git ~/javawebapp
    
  3. Passare alla cartella in cui si trova l'applicazione di esempio per questo esercizio.

    cd ~/javawebapp/ms-identity-java-servlet-webapp-authentication/2-Authorization-I/call-graph
    

Configurazione dell'applicazione

Per configurare il codice, aprire il progetto dell'applicazione nell'ambiente di sviluppo integrato preferito, ad esempio IntelliJ o VS Code.

  1. Apri il file ./src/main/resources/authentication.properties.

  2. Trovare la stringa {enter-your-tenant-id-here}. Sostituire il valore esistente con l'ID directory (tenant) (come illustrato nell'immagine seguente), perché l'app è stata registrata con l'opzione Account solo in questa directory organizzativa.

  3. Trovare la stringa {enter-your-client-id-here} e sostituire il valore esistente con l'ID applicazione (client) (clientId) dell'applicazione registrata copiata dal portale di Azure.

    Screenshot highlighting the App ID of an app registered with Microsoft Entra ID on Azure portal.

  4. Trovare la stringa {enter-your-client-secret-here} e sostituire il valore esistente con la chiave salvata durante la creazione dell'app nel portale di Azure.

Eseguire l'applicazione

  1. Verificare che il server Tomcat sia in esecuzione e di avere i privilegi per distribuirvi un'app Web. Verificare che l'indirizzo host del server sia http://localhost:8080.

  2. Compilare e creare un pacchetto del progetto usando Maven:

    cd ~/javawebapp/2-Authorization-I/call-graph
    mvn clean package
    
  3. Trovare il file .war risultante in ./target/msal4j-servlet-graph.war. Per eseguire la distribuzione in Tomcat, copiare questo file .war nella directory /webapps/ nella directory di installazione di Tomcat e avviare il server Tomcat.

  4. Aprire il browser e passare a http://localhost:8080/msal4j-servlet-graph/. Si verrà reindirizzati all'accesso con Microsoft Entra ID. Al termine dell'accesso, verrà visualizzata una pagina simile alla seguente:

    Screenshot showing user name displayed on the page after successfully signing in to sample application.

  5. Selezionare il pulsante ID Token Details (Dettagli token ID) per visualizzare alcune delle attestazioni decodificate del token ID.

Panoramica del codice di autenticazione

La maggior parte del codice di autenticazione è disponibile nell'applicazione di esempio nella directory del java/com/microsoft/azuresamples/msal4j/ progetto. Contiene più servlet che forniscono gli endpoint di autenticazione nell'applicazione per l'accesso, la disconnessione e la gestione del callback di reindirizzamento da Microsoft Entra ID. Questi servlet usano le classi helper nella directory java/com/microsoft/azuresamples/msal4j/helpers/ per chiamare i metodi di autenticazione forniti da MSAL. Esiste un filtro servlet definito in AuthenticationFilter.java che reindirizza le richieste non autenticate alle route protette a una pagina di errore HTTP non autorizzata 401.

Per aggiungere l'autenticazione all'applicazione, è necessario includere le classi servlet in java/com/microsoft/azuresamples/msal4j/authservlets e java/com/microsoft/azuresamples/msal4j/authwebapp directory, le classi helper nella directory java/com/microsoft/azuresamples/msal4j/helpers/ e il filtro AuthenticationFilter.java servlet di autenticazione nei progetti. Ecco altri dettagli del codice di autenticazione MSAL.

  1. MSAL4J è disponibile in Maven. È necessario aggiungere MSAL4J come dipendenza nel file del pom.xml progetto:

    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>msal4j</artifactId>
        <version>1.9.1</version>
    </dependency>
    
  2. Il primo passaggio del processo di accesso consiste nell'inviare una richiesta all'endpoint del tenant di /authorize Microsoft Entra. L'istanza ConfidentialClientApplication di MSAL4J viene sfruttata per costruire un URL della richiesta di autorizzazione. L'app reindirizza il browser a questo URL, dove l'utente effettuerà l'accesso.

    final ConfidentialClientApplication client = getConfidentialClientInstance();
    AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters
                                                        .builder(Config.REDIRECT_URI, Collections.singleton(Config.SCOPES))
                                                        .responseMode(ResponseMode.QUERY).prompt(Prompt.SELECT_ACCOUNT).state(state).nonce(nonce).build();
    
    final String authorizeUrl = client.getAuthorizationRequestUrl(parameters).toString();
    contextAdapter.redirectUser(authorizeUrl);
    
    • AuthorizationRequestUrlParameters: parametri da impostare per creare un elemento AuthorizationRequestUrl.
    • REDIRECT_URI: l'URI di reindirizzamento è l'URI a cui il provider di identità invierà nuovamente i token di sicurezza. Microsoft Entra ID reindirizzerà il browser (con il codice di autenticazione) a questo URI dopo aver raccolto le credenziali utente. Deve corrispondere all'URI di reindirizzamento nella registrazione dell'app Microsoft Entra.
    • SCOPES: gli ambiti sono autorizzazioni richieste dall'applicazione. In genere, i tre ambiti openid profile offline_access sono sufficienti per ricevere una risposta del token ID per un accesso utente e vengono configurati da MSAL per impostazione predefinita.
  3. L'utente riceve una richiesta di accesso da Microsoft Entra ID. Se il tentativo di accesso ha esito positivo, il browser dell'utente viene reindirizzato all'endpoint di reindirizzamento dell'app con un codice di autorizzazione valido nell'endpoint. L'istanza ConfidentialClientApplication scambia quindi questo codice di autorizzazione con un token ID e un token di accesso di Microsoft Entra ID.

    // First, validate the state, then parse any error codes in response, then extract the authCode. Then:
    // build the auth code params:
    final AuthorizationCodeParameters authParams = AuthorizationCodeParameters
                                                        .builder(authCode, new URI(Config.REDIRECT_URI)).scopes(Collections.singleton(Config.SCOPES)).build();
    
    // Get a client instance and leverage it to acquire the token:
    final ConfidentialClientApplication client = AuthHelper.getConfidentialClientInstance();
    final IAuthenticationResult result = client.acquireToken(authParams).get();
    
    • AuthorizationCodeParameters: parametri da impostare per scambiare il codice di autorizzazione con un token ID e/o di accesso.
    • authCode: codice di autorizzazione ricevuto nell'endpoint di reindirizzamento.
    • REDIRECT_URI: l'URI di reindirizzamento usato nel passaggio precedente deve essere passato di nuovo.
    • SCOPES: gli ambiti usati nel passaggio precedente devono essere passati di nuovo.
  4. Se acquireToken ha esito positivo, vengono estratte le attestazioni del token. Se il controllo di nonce viene superato, i risultati vengono inseriti in context (un'istanza di IdentityContextData) e salvati nella sessione. L'applicazione può quindi creare un'istanza dalla sessione (tramite un'istanza di IdentityContextAdapterServlet) ogni volta che deve accedervi:

    // parse IdToken claims from the IAuthenticationResult:
    // (the next step - validateNonce - requires parsed claims)
    context.setIdTokenClaims(result.idToken());
    
    // if nonce is invalid, stop immediately! this could be a token replay!
    // if validation fails, throws exception and cancels auth:
    validateNonce(context);
    
    // set user to authenticated:
    context.setAuthResult(result, client.tokenCache().serialize());