共用方式為


教學課程:從 App Service 經由後端 API 針對 Microsoft Graph 的流程驗證

了解如何建立和設定後端應用程式服務以接受前端應用程式的使用者認證,然後將該認證交換為下游 Azure 服務。 這可讓使用者登入前端應用程式服務、將其認證傳遞至後端應用程式服務,然後使用相同的身分識別存取 Azure 服務。

在本教學課程中,您會了解如何:

  • 設定後端驗證應用程式以提供將範圍設定為下游 Azure 服務的權杖
  • 使用 JavaScript 程式碼將已登入使用者的存取權杖交換為下游服務的新權杖。
  • 使用 JavaScript 程式碼來存取下游服務。

必要條件

在開始本教學課程之前,請先完成上一個教學課程:以使用者身分,從安全的 JavaScript 應用程式存取 Microsoft Graph (部分機器翻譯),但請不要在教學課程結尾移除資源。 本教學課程假設您有兩個應用程式服務及其對應的驗證應用程式。

上一個教學課程使用 Azure Cloud Shell 作為 Azure CLI 的殼層。 本教學課程會延續此使用方式。

架構

教學課程會示範如何將前端應用程式提供的使用者認證傳遞給後端應用程式,然後再傳遞至 Azure 服務。 在本教學課程中,下游服務是 Microsoft Graph。 使用者的認證是用來從 Microsoft Graph 取得其設定檔。

Architectural image of App Service connecting to App Service connecting to Microsoft Graph on behalf of a signed-in user.

讓使用者取得此結構中 Microsoft Graph 資訊的驗證流程

上一個教學課程 (部分機器翻譯) 已涵蓋:

  1. 將使用者登入設定成使用 Active Directory 作為識別提供者的前端應用程式服務。
  2. 前端應用程式服務會將使用者的權杖傳遞至後端應用程式服務。
  3. 後端應用程式已受到保護,以允許前端提出 API 要求。 使用者的存取權杖具有適用於後端 API 的對象,以及 user_impersonation 的範圍。
  4. 後端應用程式註冊已經有具有 User.Read 範圍的 Microsoft Graph。 這預設會新增至所有應用程式註冊。
  5. 在上一個教學課程的結尾,由於 Graph 未連線,會將「偽造的」設定檔傳回前端應用程式。

本教學課程會延伸該結構:

  1. 授與管理員同意以略過後端應用程式的使用者同意畫面。
  2. 變更應用程式程式碼以將從前端應用程式傳送的存取權杖轉換為具有適用於 Microsoft Graph 之必要權限的存取權杖。
  3. 提供程式碼以讓後端應用程式交換權杖,以取得具有如 Microsoft Graph 之下游 Azure 服務範圍的新權杖。
  4. 提供程式碼以讓後端應用程式使用新權杖,來以目前的驗證使用者的身分存取下游服務。
  5. 使用 az webapp up 重新部署後端應用程式。
  6. 在本教學課程的結尾,由於 Graph 已連線,會將「真實的」設定檔傳回前端應用程式。

本教學課程不會:

  • 變更上一個教學課程的前端應用程式。
  • 變更後端驗證應用程式的範圍權限,因為預設已將 User.Read 新增至所有驗證應用程式。

在上一個教學課程中,當使用者登入前端應用程式時,系統會顯示快顯要求使用者同意。

在本教學課程中,為了從 Microsoft Graph 讀取使用者設定檔,後端應用程式必須將已登入使用者的存取權杖 (部分機器翻譯) 交換為具有 Microsoft Graph 必要權限的新存取權杖。 由於使用者未直接連線到後端應用程式,因此他們無法以互動方式存取同意畫面。 您必須藉由在 Microsoft Entra ID 中設定後端應用程式的應用程式註冊以授與管理員同意 (部分機器翻譯) 來解決此問題。 這是一個通常是由 Active Directory 管理員進行的設定變更。

  1. 開啟 Azure 入口網站,並搜尋您針對後端應用程式服務的研究。

  2. 找到 [設定] -> [驗證] 區段。

  3. 選取識別提供者以移至驗證應用程式。

  4. 在驗證應用程式中,選取 [管理] -> [API 權限]

  5. 選取 [針對預設目錄授與管理員同意]

    Screenshot of Azure portal authentication app with admin consent button highlighted.

  6. 在快顯視窗中,選取 [是] 以確認同意。

  7. 確認 [狀態] 資料行顯示 [已針對預設目錄授與]。 透過此設定,後端應用程式已不再需要向已登入使用者顯示同意畫面,且可以直接要求存取權杖。 已登入使用者具有對 User.Read 範圍設定的存取權,因為其為建立應用程式註冊的預設範圍。

    Screenshot of Azure portal authentication app with admin consent granted in status column.

2.安裝 npm 套件

在上一個教學課程中,後端應用程式不需要針對驗證具備任何 npm 套件,因為唯一的驗證是透過在 Azure 入口網站中設定識別提供者來提供。 在本教學課程中,已登入使用者針對後端 API 的存取權杖必須交換成範圍包含 Microsoft Graph 的存取權杖。 此交換是使用兩個程式庫來完成,因為此交換不再使用 App Service 驗證,而是直接使用 Microsoft Entra ID 和 MSAL.js。

  1. 開啟 Azure Cloud Shell 並變更至範例目錄的後端應用程式:

    cd js-e2e-web-app-easy-auth-app-to-app/backend
    
  2. 安裝 Azure MSAL npm 套件:

    npm install @azure/msal-node
    
  3. 安裝 Microsoft Graph npm 套件:

    npm install @microsoft/microsoft-graph-client
    

3.新增程式碼以將目前的權杖交換為 Microsoft Graph 權杖

已為您提供完成此步驟的原始程式碼。 使用下列步驟來加以包括。

  1. 開啟 ./src/server.js 檔案。

  2. 將位於檔案頂端的下列相依性取消註解:

    import { getGraphProfile } from './with-graph/graph';
    
  3. 在相同的檔案中,將 graphProfile 變數取消註解:

    let graphProfile={};
    
  4. 在相同的檔案中,將 get-profile 路由中的下列 getGraphProfile 行取消註解,以從 Microsoft Graph 取得設定檔:

    // where did the profile come from
    profileFromGraph=true;
    
    // get the profile from Microsoft Graph
    graphProfile = await getGraphProfile(accessToken);
    
    // log the profile for debugging
    console.log(`profile: ${JSON.stringify(graphProfile)}`);
    
  5. 儲存變更:Ctrl + s

  6. 重新部署後端應用程式:

    az webapp up --resource-group myAuthResourceGroup --name <back-end-app-name> 
    
    

4.檢查後端程式碼以將後端 API 權杖交換為 Microsoft Graph 權杖

若要將後端 API 對象權杖變更為 Microsoft Graph 權杖,後端應用程式必須找到租用戶識別碼,並將其作為 MSAL.js 設定物件的一部分使用。 由於後端應用程式是設定為使用 Microsoft 作為識別提供者,因此租用戶識別碼和數個其他必要的值已經位於應用程式服務應用程式設定中。

已在範例應用程式中為您提供下列程式碼。 您必須了解其在那裡的原因,以及其運作方式,使您可以將此工作套用至您建置且需要此相同功能的其他應用程式。

檢查用於取得租用戶識別碼的程式碼

  1. 開啟 ./backend/src/with-graph/auth.js 檔案。

  2. 檢閱 getTenantId() 函式。

    export function getTenantId() {
    
        const openIdIssuer = process.env.WEBSITE_AUTH_OPENID_ISSUER;
        const backendAppTenantId = openIdIssuer.replace(/https:\/\/sts\.windows\.net\/(.{1,36})\/v2\.0/gm, '$1');
    
        return backendAppTenantId;
    }
    
  3. 此函式會從 WEBSITE_AUTH_OPENID_ISSUER 環境變數取得目前的租用戶識別碼。 會使用規則運算式從變數中剖析出識別碼。

檢查程式碼以使用 MSAL.js 取得 Graph 權杖

  1. 繼續在 ./backend/src/with-graph/auth.js 檔案中檢閱 getGraphToken() 函式。

  2. 建置 MSAL.js 設定物件,使用 MSAL 設定來建立 clientCredentialAuthority。 設定 on-behalf-off 要求。 然後使用 acquireTokenOnBehalfOf 將後端 API 存取權杖交換為 Graph 存取權杖。

    // ./backend/src/auth.js
    // Exchange current bearerToken for Graph API token
    // Env vars were set by App Service
    export async function getGraphToken(backEndAccessToken) {
    
        const config = {
            // MSAL configuration
            auth: {
                // the backend's authentication CLIENT ID 
                clientId: process.env.WEBSITE_AUTH_CLIENT_ID,
                // the backend's authentication CLIENT SECRET 
                clientSecret: process.env.MICROSOFT_PROVIDER_AUTHENTICATION_SECRET,
                // OAuth 2.0 authorization endpoint (v2)
                // should be: https://login.microsoftonline.com/BACKEND-TENANT-ID
                authority: `https://login.microsoftonline.com/${getTenantId()}`
            },
            // used for debugging
            system: {
                loggerOptions: {
                    loggerCallback(loglevel, message, containsPii) {
                        console.log(message);
                    },
                    piiLoggingEnabled: true,
                    logLevel: MSAL.LogLevel.Verbose,
                }
            }
        };
    
        const clientCredentialAuthority = new MSAL.ConfidentialClientApplication(config);
    
        const oboRequest = {
            oboAssertion: backEndAccessToken,
            // this scope must already exist on the backend authentication app registration 
            // and visible in resources.azure.com backend app auth config
            scopes: ["https://graph.microsoft.com/.default"]
        }
    
        // This example has App service validate token in runtime
        // from headers that can't be set externally
    
        // If you aren't using App service's authentication, 
        // you must validate your access token yourself
        // before calling this code
        try {
            const { accessToken } = await clientCredentialAuthority.acquireTokenOnBehalfOf(oboRequest);
            return accessToken;
        } catch (error) {
            console.log(`getGraphToken:error.type = ${error.type}  ${error.message}`);
        }
    }
    

5.檢查後端程式碼以使用新的權杖存取 Microsoft Graph

為了以登入前端應用程式的使用者身分存取 Microsoft Graph,變更會包括:

  • Active Directory 應用程式註冊的設定,其中包含針對下游服務 Microsoft Graph 的 API 權限,以及 User.Read 的必要範圍。
  • 授與管理員同意以略過後端應用程式的使用者同意畫面。
  • 變更應用程式程式碼以將從前端應用程式傳送的存取權杖轉換為具有適用於下游服務 Microsoft Graph 之必要權限的存取權杖。

在程式碼具有適用於 Microsoft Graph 的正確權杖之後,使用該程式碼來針對 Microsoft Graph 建立用戶端,然後取得使用者的設定檔。

  1. 開啟 ./backend/src/graph.js

  2. getGraphProfile() 函式中取得權杖,然後取得權杖中的已驗證用戶端,最後再取得設定檔。

    // 
    import graph from "@microsoft/microsoft-graph-client";
    import { getGraphToken } from "./auth.js";
    
    // Create client from token with Graph API scope
    export function getAuthenticatedClient(accessToken) {
        const client = graph.Client.init({
            authProvider: (done) => {
                done(null, accessToken);
            }
        });
    
        return client;
    }
    export async function getGraphProfile(accessToken) {
        // exchange current backend token for token with 
        // graph api scope
        const graphToken = await getGraphToken(accessToken);
    
        // use graph token to get Graph client
        const graphClient = getAuthenticatedClient(graphToken);
    
        // get profile of user
        const profile = await graphClient
            .api('/me')
            .get();
    
        return profile;
    }
    

6.測試您的變更

  1. 在瀏覽器中使用前端網站。 URL 的格式為 https://<front-end-app-name>.azurewebsites.net/。 如果您的權杖已過期,您可能需要加以重新整理。

  2. 選取 Get user's profile。 這會將您持有人權杖中的驗證傳遞至後端。

  3. 後端會以您帳戶「真實的」Microsoft Graph 設定檔回應。

    Screenshot of web browser showing frontend application after successfully getting real profile from backend app.

7.清除

在上述步驟中,您已建立資源群組中的 Azure 資源。

  1. 在 Cloud Shell 中執行下列命令,以刪除資源群組。 此命令可能會花一分鐘執行。

    az group delete --name myAuthResourceGroup
    
  2. 在後端和前端應用程式的 Enable authentication and authorization 區段中使用您先前找到並記下的驗證應用程式用戶端識別碼

  3. 刪除前端和後端應用程式的應用程式註冊。

    # delete app - do this for both frontend and backend client ids
    az ad app delete <client-id>
    

常見問題集

我收到 80049217 錯誤,這代表什麼意思?

CompactToken parsing failed with error code: 80049217 的錯誤表示後端應用程式未獲授權傳回 Microsoft Graph 權杖。 此錯誤的原因是因為應用程式註冊缺少 User.Read 權限。

我收到 AADSTS65001 錯誤,這代表什麼意思?

AADSTS65001: The user or administrator has not consented to use the application with ID \<backend-authentication-id>. Send an interactive authorization request for this user and resource 的錯誤表示後端驗證應用程式未針對管理員同意進行設定。 由於該錯誤會出現在後端應用程式的記錄中,前端應用程式無法告訴使用者他們為什麼無法在前端應用程式中看見其設定檔。

我如何以使用者的身分連線到不同的下游 Azure 服務?

本教學課程示範驗證至 Microsoft Graph 的 API 應用程式,不過相同的一般步驟也可以套用到代表使用者存取任何 Azure 服務的案例。

  1. 不用對前端應用程式進行任何變更。 只需對後端的驗證應用程式註冊和後端應用程式原始程式碼進行變更。
  2. 將使用者以後端 API 為範圍的權杖交換為您想要存取之下游服務的權杖。
  3. 在下游服務的 SDK 中使用權杖來建立用戶端。
  4. 使用下游用戶端來存取服務功能。

下一步