教學課程:處理 Vanilla JavaScript SPA 中的驗證流程
本教學課程是系列的第 3 部分,示範如何建置 Vanilla JavaScript (JS) 單頁應用程式 (SPA),並準備對其進行驗證。 在此系列的第 2 部分中,您已建立 Vanilla JS SPA,並準備使用外部租用戶,對其進行驗證。 在本教學課程中,您會了解如何藉由新增 Microsoft 驗證程式庫 (MSAL) 元件來處理應用程式中的驗證流程。
在本教學課程中:
- 設定應用程式的設定
- 將程式碼新增至 authRedirect.js 以處理驗證流程
- 將程式碼新增至 authPopup.js 以處理驗證流程
必要條件
編輯驗證設定檔
開啟公用/authConfig.js,並新增下列程式碼片段:
import { LogLevel } from '@azure/msal-browser'; /** * Configuration object to be passed to MSAL instance on creation. * For a full list of MSAL.js configuration parameters, visit: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/configuration.md */ export const msalConfig = { auth: { clientId: 'Enter_the_Application_Id_Here', // This is the ONLY mandatory field that you need to supply. authority: 'https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com/', // Replace the placeholder with your tenant subdomain redirectUri: '/', // Points to window.location.origin. You must register this URI on Azure Portal/App Registration. postLogoutRedirectUri: '/', // Indicates the page to navigate after logout. navigateToLoginRequestUrl: false, // If "true", will navigate back to the original request location before processing the auth code response. }, cache: { cacheLocation: 'sessionStorage', // Configures cache location. "sessionStorage" is more secure, but "localStorage" gives you SSO between tabs. storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge }, system: { loggerOptions: { loggerCallback: (level, message, containsPii) => { if (containsPii) { return; } switch (level) { case LogLevel.Error: console.error(message); return; case LogLevel.Info: console.info(message); return; case LogLevel.Verbose: console.debug(message); return; case LogLevel.Warning: console.warn(message); return; default: return; } }, }, }, }; /** * Scopes you add here will be prompted for user consent during sign-in. * By default, MSAL.js will add OIDC scopes (openid, profile, email) to any login request. * For more information about OIDC scopes, visit: * https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes */ export const loginRequest = { scopes: [], };
將下列值取代為 Azure 入口網站中的值:
- 尋找
Enter_the_Application_Id_Here
值,並將它取代為您在 Microsoft Entra 系統管理中心註冊之應用程式的 應用程式識別碼 (clientId)。- 在 [授權單位] 中,尋找
Enter_the_Tenant_Subdomain_Here
並將其取代為您租用戶的子網域。 例如,如果您的租用戶主要網域是contoso.onmicrosoft.com
,請使用contoso
。 如果您沒有租用戶名稱,請了解如何讀取租用戶詳細資料。
- 在 [授權單位] 中,尋找
- 尋找
儲存檔案。
使用自訂 URL 網域 (選用)
使用自訂網域對驗證 URL 進行完整品牌化。 就使用者而言,使用者在驗證過程中一直停留在您的網域中,而不會重新導向至 ciamlogin.com 網域名稱。
使用下列步驟來使用自訂網域:
使用針對外部租用戶中的應用程式啟用自訂 URL 網域中的步驟,為外部租用戶啟用自訂 URL 網域。
在您的 authConfig.js 檔案中,找出
auth
物件,然後:- 將
authority
屬性的值更新為 https://Enter_the_Custom_Domain_Here/Enter_the_Tenant_ID_Here。 以您的自訂 URL 網域取代Enter_the_Custom_Domain_Here
,並以您的租用戶識別碼取代Enter_the_Tenant_ID_Here
。 如果您沒有租用戶識別碼,請了解如何讀取租用戶詳細資料。 - 新增具有值 [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
},
//...
};
將程式碼新增至重新導向檔案
需要重新導向檔案,才能處理來自登入頁面的回應。 它用來從 URL 片段擷取存取權杖,並用它來呼叫受保護的 API。 它也可用來處理驗證流程期間發生的錯誤。
開啟公用/authRedirect.js,並新增下列程式碼片段:
// Create the main myMSALObj instance // configuration parameters are located at authConfig.js const myMSALObj = new msal.PublicClientApplication(msalConfig); let username = ""; /** * A promise handler needs to be registered for handling the * response returned from redirect flow. For more information, visit: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/initialization.md#redirect-apis */ myMSALObj.handleRedirectPromise() .then(handleResponse) .catch((error) => { console.error(error); }); function selectAccount() { /** * See here for more info on account retrieval: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md */ const currentAccounts = myMSALObj.getAllAccounts(); if (!currentAccounts) { return; } else if (currentAccounts.length > 1) { // Add your account choosing logic here console.warn("Multiple accounts detected."); } else if (currentAccounts.length === 1) { username = currentAccounts[0].username welcomeUser(currentAccounts[0].username); updateTable(currentAccounts[0]); } } function handleResponse(response) { /** * To see the full list of response object properties, visit: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#response */ if (response !== null) { username = response.account.username welcomeUser(username); updateTable(response.account); } else { selectAccount(); } } function signIn() { /** * You can pass a custom request object below. This will override the initial configuration. For more information, visit: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request */ myMSALObj.loginRedirect(loginRequest); } function signOut() { /** * You can pass a custom request object below. This will override the initial configuration. For more information, visit: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request */ // Choose which account to logout from by passing a username. const logoutRequest = { account: myMSALObj.getAccountByUsername(username), postLogoutRedirectUri: '/signout', // remove this line if you would like navigate to index page after logout. }; myMSALObj.logoutRedirect(logoutRequest); }
儲存檔案。
將程式碼新增至 authPopup.js 檔案
當使用者使用彈出視窗登入時,應用程式會使用 authPopup.js 來處理驗證流程。 當使用者已經登入,而且應用程式需要取得不同資源的存取權杖時,就會使用彈出視窗。
開啟公用/authPopup.js,並新增下列程式碼片段:
// Create the main myMSALObj instance // configuration parameters are located at authConfig.js const myMSALObj = new msal.PublicClientApplication(msalConfig); let username = ""; function selectAccount () { /** * See here for more info on account retrieval: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md */ const currentAccounts = myMSALObj.getAllAccounts(); if (!currentAccounts || currentAccounts.length < 1) { return; } else if (currentAccounts.length > 1) { // Add your account choosing logic here console.warn("Multiple accounts detected."); } else if (currentAccounts.length === 1) { username = currentAccounts[0].username welcomeUser(currentAccounts[0].username); updateTable(currentAccounts[0]); } } function handleResponse(response) { /** * To see the full list of response object properties, visit: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#response */ if (response !== null) { username = response.account.username welcomeUser(username); updateTable(response.account); } else { selectAccount(); } } function signIn() { /** * You can pass a custom request object below. This will override the initial configuration. For more information, visit: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request */ myMSALObj.loginPopup(loginRequest) .then(handleResponse) .catch(error => { console.error(error); }); } function signOut() { /** * You can pass a custom request object below. This will override the initial configuration. For more information, visit: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request */ // Choose which account to logout from by passing a username. const logoutRequest = { account: myMSALObj.getAccountByUsername(username), mainWindowRedirectUri: '/signout' }; myMSALObj.logoutPopup(logoutRequest); } selectAccount();
儲存檔案。