分享方式:


教學課程:在您的 Node.js Web 應用程式中新增登入和登出

本教學課程是系列中的最後一個部分,示範如何使用 Microsoft Entra 系統管理中心來建置 Node.js Web 應用程式並準備進行驗證。 在此系列的第 2 部分中,您已建立 Node.js Web 應用程式並組織所有必要的檔案。 在本教學課程中,您將新增 Node.js Web 應用程式的登入、註冊和登出。 若要簡化將驗證新增至 Node.js Web 應用程式,您可使用適用於 Node 的 Microsoft 驗證程式庫 (MSAL)。 登入流程會使用 OpenID Connect (OIDC) 驗證通訊協定,安全地登入使用者。

在本教學課程中,您將會:

  • 增登入和登出邏輯
  • 檢視 ID 權杖宣告
  • 執行應用程式及測試登入和登出體驗。

必要條件

建立 MSAL 設定物件

在您的程式碼編輯器中,開啟 authConfig.js 檔案,然後新增下列程式碼:

require('dotenv').config();

const TENANT_SUBDOMAIN = process.env.TENANT_SUBDOMAIN || 'Enter_the_Tenant_Subdomain_Here';
const REDIRECT_URI = process.env.REDIRECT_URI || 'http://localhost:3000/auth/redirect';
const POST_LOGOUT_REDIRECT_URI = process.env.POST_LOGOUT_REDIRECT_URI || 'http://localhost:3000';

/**
 * Configuration object to be passed to MSAL instance on creation.
 * For a full list of MSAL Node configuration parameters, visit:
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/configuration.md
 */
const msalConfig = {
    auth: {
        clientId: process.env.CLIENT_ID || 'Enter_the_Application_Id_Here', // 'Application (client) ID' of app registration in Azure portal - this value is a GUID
        authority: process.env.AUTHORITY || `https://${TENANT_SUBDOMAIN}.ciamlogin.com/`, // replace "Enter_the_Tenant_Subdomain_Here" with your tenant name
        clientSecret: process.env.CLIENT_SECRET || 'Enter_the_Client_Secret_Here', // Client secret generated from the app registration in Azure portal
    },
    system: {
        loggerOptions: {
            loggerCallback(loglevel, message, containsPii) {
                console.log(message);
            },
            piiLoggingEnabled: false,
            logLevel: 'Info',
        },
    },
};

module.exports = {
    msalConfig,
    REDIRECT_URI,
    POST_LOGOUT_REDIRECT_URI,
    TENANT_SUBDOMAIN
};

msalConfig 物件包含一組設定選項,可用來自訂驗證流程的行為。

authConfig.js 檔案中,取代:

  • Enter_the_Application_Id_Here 成為您稍早所註冊應用程式的應用程式 (用戶端) 識別碼。

  • Enter_the_Tenant_Subdomain_Here 並將它取代為 Directory (租用戶) 子網域。 例如,若租用戶主要網域是 contoso.onmicrosoft.com,請使用 contoso。 如果您沒有租用戶名稱,請了解如何閱讀租用戶詳細資料

  • Enter_the_Client_Secret_Here 成為您稍早複製的應用程式秘密值。

如果您使用 .env 檔案來儲存組態資訊:

  1. 在程式碼編輯器中,開啟 .env 檔案,然後新增下列程式碼。

        CLIENT_ID=Enter_the_Application_Id_Here
        TENANT_SUBDOMAIN=Enter_the_Tenant_Subdomain_Here
        CLIENT_SECRET=Enter_the_Client_Secret_Here
        REDIRECT_URI=http://localhost:3000/auth/redirect
        POST_LOGOUT_REDIRECT_URI=http://localhost:3000
    
  2. 如先前所述,取代 Enter_the_Application_Id_HereEnter_the_Tenant_Subdomain_HereEnter_the_Client_Secret_Here 預留位置。

您可以在 authConfig.js 檔案中匯出 msalConfigREDIRECT_URITENANT_SUBDOMAINPOST_LOGOUT_REDIRECT_URI 變數,以在您需要檔案時存取這些變數。

使用自訂 URL 網域 (選用)

使用自訂網域對驗證 URL 進行完整品牌化。 就使用者而言,使用者在驗證過程中一直停留在您的網域中,而不會重新導向至 ciamlogin.com 網域名稱。

使用下列步驟來使用自訂網域:

  1. 使用針對外部租用戶中的應用程式啟用自訂 URL 網域中的步驟,為外部租用戶啟用自訂 URL 網域。

  2. 在您的 authConfig.js 檔案中,找出 auth 物件,然後:

    1. authority 屬性的值更新為 https://Enter_the_Custom_Domain_Here/Enter_the_Tenant_ID_Here。 以您的自訂 URL 網域取代 Enter_the_Custom_Domain_Here,並以您的租用戶識別碼取代 Enter_the_Tenant_ID_Here。 如果您沒有租用戶識別碼,請了解如何讀取租用戶詳細資料
    2. 新增具有值 [Enter_the_Custom_Domain_Here]knownAuthorities 屬性。

authConfig.js 檔案進行變更之後,如果您的自訂 URL 網域為 login.contoso.com,且您的租用戶識別碼為 aaaabbbb-0000-cccc-1111-dddd2222eeee,則您的檔案看起來應該類似以下程式碼片段:

//...
const msalConfig = {
    auth: {
        authority: process.env.AUTHORITY || 'https://login.contoso.com/aaaabbbb-0000-cccc-1111-dddd2222eeee', 
        knownAuthorities: ["login.contoso.com"],
        //Other properties
    },
    //...
};

新增 Express 路由

Express 路由提供端點,可讓我們執行登入、登出和檢視 ID 權杖宣告等作業。

套用進入點

在您的程式碼編輯器中,開啟 routes/index.js 檔案,然後新增下列程式碼:

const express = require('express');
const router = express.Router();

router.get('/', function (req, res, next) {
    res.render('index', {
        title: 'MSAL Node & Express Web App',
        isAuthenticated: req.session.isAuthenticated,
        username: req.session.account?.username !== '' ? req.session.account?.username : req.session.account?.name,
    });
});    
module.exports = router;

/ 路由是應用程式的進入點。 它會轉譯您稍早在建置應用程式 UI 元件中建立的 views/index.hbs 檢視。 isAuthenticated 是一個布林值變數,可決定您在檢視中看到的內容。

登入和登出

  1. 在程式碼編輯器中,開啟 routes/auth.js 檔案,然後將程式碼從 auth.js 新增至其中。

  2. 在程式碼編輯器中,開啟 controller/authController.js 檔案,然後將程式碼從 authController.js 新增至其中。

  3. 在程式碼編輯器中,開啟 auth/AuthProvider.js 檔案,然後將程式碼從 AuthProvider.js 新增至其中。

    /signin/signout/redirect 路由定義於 routes/auth.js 檔案中,但您會在 auth/AuthProvider.js 類別中實作其邏輯。

  • login 方法會處理 /signin 路由:

    • 它會觸授權碼流程的第一段來起始登入流程。

    • 它會使用您稍早建立的 MSAL 組態物件 msalConfig,初始化機密用戶端應用程式執行個體。

          const msalInstance = this.getMsalInstance(this.config.msalConfig);
      

      getMsalInstance 方法已定義為:

          getMsalInstance(msalConfig) {
              return new msal.ConfidentialClientApplication(msalConfig);
          }
      
    • 授權碼流程的第一段會產生授權碼要求 URL,然後重新導向至該 URL 以取得授權碼。 第一段是在 redirectToAuthCodeUrl 方法中實作。 請注意我們如何使用 MSALs getAuthCodeUrl 方法來產生授權碼 URL:

      //...
      const authCodeUrlResponse = await msalInstance.getAuthCodeUrl(req.session.authCodeUrlRequest);
      //...
      

      然後,我們會重新導向至授權碼 URL 本身。

      //...
      res.redirect(authCodeUrlResponse);
      //...
      
  • handleRedirect 方法會處理 /redirect 路由:

    • 您稍早註冊 Web 應用程式時,在 Microsoft Entra 系統管理中心將此 URL 設定為 Web 應用程式的重新導向 URI。

    • 此端點會實作授權碼流程使用的第二段。 它會使用 MSAL 的 acquireTokenByCode 方法,使用授權碼來要求 ID 權杖。

      //...
      const tokenResponse = await msalInstance.acquireTokenByCode(authCodeRequest, req.body);
      //...
      
    • 收到回應之後,您可以建立 Express 工作階段並將您想要的任何資訊儲存在其中。 您需要包含 isAuthenticated 並將它設定為 true

      //...        
      req.session.idToken = tokenResponse.idToken;
      req.session.account = tokenResponse.account;
      req.session.isAuthenticated = true;
      //...
      
  • logout 方法會處理 /signout 路由:

    async logout(req, res, next) {
        /**
         * Construct a logout URI and redirect the user to end the
            * session with Azure AD. For more information, visit:
            * https://docs.microsoft.com/azure/active-directory/develop/v2-protocols-oidc#send-a-sign-out-request
            */
        const logoutUri = `${this.config.msalConfig.auth.authority}${TENANT_SUBDOMAIN}.onmicrosoft.com/oauth2/v2.0/logout?post_logout_redirect_uri=${this.config.postLogoutRedirectUri}`;
    
        req.session.destroy(() => {
            res.redirect(logoutUri);
        });
    }
    
    • 它會起始登出要求。

    • 當您想要將使用者登出應用程式時,這不足以結束使用者的工作階段。 您必須將使用者重新導向至 logoutUri。 不然,使用者也許能夠向您的應用程式進行重新驗證,而不需要重新輸入其認證。 如果您的租用戶名稱是 contoso,則 logoutUri 看起來類似 https://contoso.ciamlogin.com/contoso.onmicrosoft.com/oauth2/v2.0/logout?post_logout_redirect_uri=http://localhost:3000

檢視 ID 權杖宣告

在您的程式碼編輯器中,開啟 routes/users.js 檔案,然後新增下列程式碼:

const express = require('express');
const router = express.Router();

// custom middleware to check auth state
function isAuthenticated(req, res, next) {
    if (!req.session.isAuthenticated) {
        return res.redirect('/auth/signin'); // redirect to sign-in route
    }

    next();
};

router.get('/id',
    isAuthenticated, // check if user is authenticated
    async function (req, res, next) {
        res.render('id', { idTokenClaims: req.session.account.idTokenClaims });
    }
);        
module.exports = router;

如果使用者經過驗證,/id 路由會使用 views/id.hbs 檢視來顯示 ID 權杖宣告。 您稍早在建置應用程式 UI 元件中新增了此檢視。

若要擷取特定 ID 權杖宣告,例如指定的名稱

const givenName = req.session.account.idTokenClaims.given_name

完成您的 Web 應用程式

  1. 在程式碼編輯器中,開啟 app.js 檔案,然後將程式碼從 app.js 新增至其中。

  2. 在程式碼編輯器中,開啟 server.js 檔案,然後將程式碼從 server.js 新增至其中。

  3. 在程式碼編輯器中,開啟 package.json 檔案,然後將 scripts 屬性更新為:

    "scripts": {
    "start": "node server.js"
    }
    

執行並測試 Web 應用程式

  1. 在您的終端機中,確定您位於包含 Web 應用程式的專案資料夾中,例如 ciam-sign-in-node-express-web-app

  2. 在終端內,執行下列 命令:

    npm start
    
  3. 開啟瀏覽器,然後移至 http://localhost:3000。 您應該會看到類似下列螢幕擷取畫面的頁面:

    登入節點 Web 應用程式的螢幕擷取畫面。

  4. 頁面完成載入之後,請選取 [登入] 連結。 系統會提示您登入。

  5. 在登入頁面上,輸入您的 [電子郵件地址]、選取 [下一步]、輸入您的 [密碼],然後選取 [登入]。 如果您沒有帳戶,請選取 [沒有帳戶?建立一個] 連結,以啟動註冊流程。

  6. 如果您選擇註冊選項,在填寫電子郵件、一次性密碼、新密碼和更多帳戶詳細資料之後,您便能完成整個註冊流程。 您會看到類似下列螢幕擷取畫面的頁面。 如果您選擇登入選項,則會看到類似的頁面。

    檢視 ID 權杖宣告的螢幕擷取畫面。

  7. 選取 [登出] 將使用者登出 Web 應用程式,或選取 [檢視 ID 權杖宣告] 以檢視所有 ID 權杖宣告。

另請參閱