練習 - 使用 MSAL 登入使用者

已完成

在此練習中,您將使用適用於 Java 的 Microsoft 驗證程式庫 (MSAL4J) 在範例 Java Web 應用程式中新增驗證,讓使用者能夠使用其 Microsoft Entra 帳戶進行登入。

此練習中使用的範例應用程式是 Java Servlet 應用程式,可讓使用者登入並顯示使用者名稱和基本設定檔資訊。 您可藉此呼叫 Microsoft Graph API,以顯示一些使用者資訊。

建立 JAVA Web 應用程式

從殼層或命令列:

  1. 建立應用程式的資料夾。

    mkdir ~/javawebapp
    
  2. 將範例應用程式從 GitHub 存放庫複製到新資料夾。

    git clone https://github.com/Azure-Samples/ms-identity-java-servlet-webapp-authentication.git ~/javawebapp
    
  3. 切換至此練習的範例應用程式所在的資料夾。

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

設定應用程式

若要設定程式碼,請在您慣用的 IDE 中開啟應用程式專案,例如 IntelliJ 或 VS Code。

  1. 開啟 ./src/main/resources/authentication.properties 檔案。

  2. aad.authority 屬性中,尋找字串 {enter-your-tenant-id-here}。 將現有值取代為 目錄 (租用戶) 識別碼值 (如下圖所示),因為應用程式是使用 [僅限此組織目錄中的帳戶] 選項註冊。

  3. aad.clientId 屬性中,找到字串 {enter-your-client-id-here},並將現有值取代為已註冊並從 Azure 入口網站複製的應用程式的應用程式 (用戶端) 識別碼值 - clientId 值。

    強調顯示 Azure 入口網站上已使用 Microsoft Entra ID 註冊的應用程式的應用程式識別碼的螢幕擷取畫面。

  4. aad.secret 屬性中,尋找字串 {enter-your-client-secret-here},並將現有值取代為您在 Azure 入口網站中建立應用程式時所儲存的 [金鑰] 值。

執行應用程式

  1. 確定您的 Tomcat 伺服器正在執行,且您有權將 Web 應用程式部署至該伺服器。 確定您的伺服器主機位址是 http://localhost:8080

  2. 使用 Maven 編譯並封裝專案:

    cd ~/javawebapp/2-Authorization-I/call-graph
    mvn clean package
    
  3. ./target/msal4j-servlet-graph.war 尋找產生的 .war 檔案。 若要部署至 Tomcat,請將這個 .war 檔案複製到 Tomcat 安裝目錄中的 /webapps/ 目錄,然後啟動 Tomcat 伺服器。

  4. 請開啟瀏覽器,然後瀏覽至 http://localhost:8080/msal4j-servlet-graph/。 系統會將您重新導向至使用 Microsoft Entra ID 登入。 成功登入時,您應該會看到如下的頁面:

    此螢幕擷取畫面顯示在成功登入範例應用程式後顯示於頁面上的使用者名稱。

  5. 選取 [識別碼權杖詳細資料] 按鈕,以查看某些識別碼權杖的解碼宣告。

驗證碼概觀

您可以在專案 java/com/microsoft/azuresamples/msal4j/ 目錄下的範例應用程式中找到大部分的驗證碼。 其中包含多個 Servlet,可在應用程式中提供驗證端點,用於登入、登出,以及處理來自 Microsoft Entra ID 的重新導向回撥。 這些 servlet 會使用目錄 java/com/microsoft/azuresamples/msal4j/helpers/ 中的協助程式類別來呼叫 MSAL 提供的驗證方法。 在 AuthenticationFilter.java 中定義的 Servlet 篩選會將未經驗證的要求重新導向至受保護的路由,而連至 401 未授權的 HTTP 錯誤頁面。

若要將驗證新增至您的應用程式,您必須將 Servlet 類別包含在 java/com/microsoft/azuresamples/msal4j/authservletsjava/com/microsoft/azuresamples/msal4j/authwebapp 目錄下、將協助程式類別包含在目錄 java/com/microsoft/azuresamples/msal4j/helpers/ 中,並將驗證 Servlet 篩選 AuthenticationFilter.java 包含在您的專案中。 以下是 MSAL 驗證碼的詳細資料。

  1. MSAL4J 可在 Maven 上取得。 您必須在專案的 pom.xml 檔案中將 MSAL4J 新增為相依性:

    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>msal4j</artifactId>
        <version>1.17.2</version>
    </dependency>
    
  2. 登入程序的第一個步驟是將要求傳送至 Microsoft Entra 租用戶的 /authorize 端點。 可利用 MSAL4J ConfidentialClientApplication 執行個體來建構授權要求 URL。 應用程式會將瀏覽器重新導向至此 URL,這是使用者登入的位置。 下列程式碼是 AuthHelper 類別中 redirectToAuthorizationEndpoint 方法實作的摘錄。

    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:必須設定才能建置 AuthorizationRequestUrl 的參數。
    • REDIRECT_URI:重新導向 URI 是識別提供者將傳回安全性權杖的目標 URI。 Microsoft Entra ID 會在收集使用者認證後,將瀏覽器以及驗證碼重新導向至此 URI。 這必須符合 Microsoft Entra 應用程式註冊中的重新導向 URI。
    • SCOPES:範圍是應用程式所要求的權限。 一般來說,openid profile offline_access 這三個範圍即足以接收使用者登入的識別碼權杖回應,而 MSAL 依預設會設定這些範圍。
  3. 使用者會看到 Microsoft Entra ID 發出的登入提示。 如果登入嘗試成功,則會將使用者的瀏覽器重新導向至我們應用程式的重新導向端點 (端點中具有有效的授權碼)。 然後,ConfidentialClientApplication 執行個體會以此授權碼交換來自 Microsoft Entra ID 的識別碼權杖和存取權杖。 下列程式碼是 AuthHelper 類別中 processAADCallback 方法實作的摘錄。

    // 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:必須設定才能以授權碼交換識別碼和/或存取權杖的參數。
    • authCode:在重新導向端點接收到的授權碼。
    • REDIRECT_URI:必須再次傳入在先前的步驟中使用的重新導向 URI。
    • SCOPES:必須再次傳入在先前的步驟中使用的範圍。
  4. 如果 acquireToken 成功,則會擷取權杖宣告。 如果通過 nonce 檢查,結果將會放在 context (IdentityContextData 的執行個體) 中,並儲存至工作階段。 然後,每當應用程式需要存取時,就可以從工作階段 (藉由 IdentityContextAdapterServlet 的執行個體) 將其具現化:

    // 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());