Учебник: Добавление процессов входа и выхода в JavaScript SPA
В этом руководстве описана настройка одностраничного приложения JavaScript (SPA) для проверки подлинности. В части №1 этой сериивы создали JavaScript SPA и подготовили его для аутентификации. В этом руководстве вы узнаете, как добавить потоки аутентификации, добавив компоненты библиотеки аутентификации Microsoft (MSAL) в ваше приложение и создавая адаптивный пользовательский интерфейс для вашего приложения.
В этом руководстве:
- Добавление кода в auth.js для обработки потока проверки подлинности
- Создание пользовательского интерфейса для приложения
Необходимые условия
Добавление кода в файл перенаправления
Поток проверки подлинности — это ряд шагов, которые приложение принимает для проверки подлинности пользователя. Auth.js содержит функции, которые используются для обработки потока проверки подлинности, включая вход и выход с помощью метода перенаправления или всплывающего окна.
Откройте public/auth.js и добавьте следующий код:
// Browser check variables: If you support IE, our recommendation is to sign-in using Redirect APIs. If you are testing using Edge InPrivate mode, please add "isEdge" to the if check. const ua = window.navigator.userAgent; const msie = ua.indexOf("MSIE "); const msie11 = ua.indexOf("Trident/"); const msedge = ua.indexOf("Edge/"); const isIE = msie > 0 || msie11 > 0; const isEdge = msedge > 0; let signInType; let accountId = ""; // myMSALObj instance - configuration parameters are located at authConfig.js const myMSALObj = new msal.PublicClientApplication(msalConfig); myMSALObj.initialize().then(() => { // Redirect: once login is successful and redirects with tokens, call Graph API myMSALObj.handleRedirectPromise().then(handleResponse).catch(err => { console.error(err); }); }) 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 showWelcomeMessage(currentAccounts[0].username); updateTable(currentAccounts[0]); } } function handleResponse(resp) { if (resp !== null) { accountId = resp.account.homeAccountId; myMSALObj.setActiveAccount(resp.account); showWelcomeMessage(resp.account); } else { selectAccount(); } } async function signIn(method) { signInType = isIE ? "redirect" : method; if (signInType === "popup") { return myMSALObj.loginPopup({ ...loginRequest, redirectUri: "/redirect" }).then(handleResponse).catch(function (error) { console.log(error); }); } else if (signInType === "redirect") { return myMSALObj.loginRedirect(loginRequest) } } function signOut(interactionType) { const logoutRequest = { account: myMSALObj.getAccountByHomeId(accountId) }; if (interactionType === "popup") { myMSALObj.logoutPopup(logoutRequest).then(() => { window.location.reload(); }); } else { myMSALObj.logoutRedirect(logoutRequest); } } // This function can be removed if you do not need to support IE async function getTokenRedirect(request, account) { return await myMSALObj.acquireTokenSilent(request).catch(async (error) => { console.log("silent token acquisition fails."); if (error instanceof msal.InteractionRequiredAuthError) { // fallback to interaction when silent call fails console.log("acquiring token using redirect"); myMSALObj.acquireTokenRedirect(request); } else { console.error(error); } }); }
Сохраните файл.
Создание пользовательского интерфейса для приложения
При настройке авторизации пользовательский интерфейс можно создать для взаимодействия с приложением при запуске проекта. Bootstrap используется для создания адаптивного пользовательского интерфейса, содержащего кнопку входа и кнопку выхода. Пользовательский интерфейс также содержит таблицу, отображающую утверждения из токена, которые будут добавлены дальше в этом руководстве.
Добавление кода в файл index.html
Главная страница SPA, index.html, — это первая страница, загруженная при запуске приложения. Это также страница, загружаемая при выборе кнопки Выход. Страница содержит панель навигации, приветственное сообщение с электронной почтой пользователя и таблицу, отображающую утверждения из токена.
Откройте общедоступный/index.html и добавьте следующий фрагмент кода:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no"> <title>Microsoft identity platform</title> <link rel="SHORTCUT ICON" href="./favicon.svg" type="image/x-icon"> <link rel="stylesheet" href="./styles.css"> <!-- adding Bootstrap 5 for UI components --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous"> <!-- msal.min.js can be used in the place of msal-browser.js --> <script src="/msal-browser.min.js"></script> </head> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Bootstrap 5 Navbar</title> <!-- Bootstrap 5 CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Rl3l94faQlfdS3b8SpxyDkgOn+Y5Qu3og6JpNZnN9LfX9k8wAI5" crossorigin="anonymous"> </head> <body> <!-- Navbar --> <nav class="navbar navbar-expand-sm navbar-dark bg-primary navbarStyle"> <a class="navbar-brand" href="/">Microsoft identity platform</a> <div class="ms-auto d-flex align-items-center"> <!-- Dropdown group (Bootstrap 5 uses dropstart instead of dropleft) --> <div class="btn-group dropstart"> <!-- Toggle button for dropdown --> <button id="signIn" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" > Sign In </button> <!-- Dropdown menu --> <div class="dropdown-menu"> <button class="dropdown-item" id="popup" onclick="signIn(this.id)"> Sign in using Popup </button> <button class="dropdown-item" id="redirect" onclick="signIn(this.id)"> Sign in using Redirect </button> </div> </div> <!-- Sign Out button --> <button class="btn btn-secondary ms-2" id="signOut" onclick="signOut()"> Sign Out </button> </div> </nav> <br /> <div class="container"> <div class="row"> <h5 id="title-div" class="card-header text-center"> JavaScript single-page application secured with MSAL.js </h5> <br /> <h5 id="welcome-div" class="card-header text-center d-none"></h5> <table class="table table-striped table-bordered d-none" id="table-div"> <thead> <tr> <th>Claim Type</th> <th>Value</th> <th>Description</th> </tr> </thead> <tbody id="table-body-div"></tbody> </table> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"> </script> <!-- Bootstrap 5 JS bundle (includes Popper) --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"> </script> <!-- Your custom scripts --> <script type="text/javascript" src="./authConfig.js"></script> <script type="text/javascript" src="./ui.js"></script> <script type="text/javascript" src="./claimUtils.js"></script> <script type="text/javascript" src="./auth.js"></script> </body> </html>
Сохраните файл.
Добавление кода в файл ui.js
Чтобы сделать приложение интерактивным, файл ui.js используется для обработки элементов пользовательского интерфейса приложения. Файл содержит функции, которые используются для обновления имени пользователя при входе в систему и для обновления таблицы с утверждениями из токена.
Откройте public/ui.js и добавьте следующий фрагмент кода:
// Select DOM elements to work with const signInButton = document.getElementById('signIn'); const signOutButton = document.getElementById('signOut'); const titleDiv = document.getElementById('title-div'); const welcomeDiv = document.getElementById('welcome-div'); const tableDiv = document.getElementById('table-div'); const tableBody = document.getElementById('table-body-div'); function showWelcomeMessage(account) { signInButton.classList.add('d-none'); signOutButton.classList.remove('d-none'); titleDiv.classList.add('d-none'); welcomeDiv.classList.remove('d-none'); welcomeDiv.innerHTML = `Welcome ${account.username}!`; updateTable(account); }; function updateTable(account) { tableDiv.classList.remove('d-none'); const tokenClaims = createClaimsTable(account.idTokenClaims); Object.keys(tokenClaims).forEach((key) => { let row = tableBody.insertRow(0); let cell1 = row.insertCell(0); let cell2 = row.insertCell(1); let cell3 = row.insertCell(2); cell1.innerHTML = tokenClaims[key][0]; cell2.innerHTML = tokenClaims[key][1]; cell3.innerHTML = tokenClaims[key][2]; }); };
Сохраните файл.
Добавление кода в файл signout.html
Файл signout.html используется для отображения сообщения пользователю при выходе из приложения.
Откройте public/signout.html и добавьте следующий фрагмент кода:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Microsoft Entra ID | JavaScript SPA</title> <link rel="SHORTCUT ICON" href="./favicon.svg" type="image/x-icon"> <!-- adding Bootstrap 4 for UI components --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> </head> <body> <div class="jumbotron" style="margin: 10%"> <h1>Goodbye!</h1> <p>You have signed out and your cache has been cleared.</p> <a class="btn btn-primary" href="/" role="button">Take me back</a> </div> </body> </html>
Сохраните файл.
Добавление стилей в приложение
Наконец, добавьте в приложение некоторые стили, чтобы сделать его более привлекательным. Стили добавляются в файл styles.css и могут быть настроены в соответствии с вашими потребностями.
Откройте public/styles.css и добавьте следующий фрагмент кода:
.navbarStyle { padding: .5rem 1rem !important; } .table-responsive-ms { max-height: 39rem !important; padding-left: 10%; padding-right: 10%; }
Сохраните файл.
Следующий шаг
Войдите и выйдите из JS SPA