Sdílet prostřednictvím


Povolte ověřování ve vlastní jednostránkové aplikaci pomocí Azure AD B2C

Důležité

Od 1. května 2025 už nebude Azure AD B2C k dispozici k nákupu pro nové zákazníky. Další informace najdete v našich nejčastějších dotazech.

Tento článek ukazuje, jak přidat ověřování Azure Active Directory B2C (Azure AD B2C) do vlastní jednostránkové aplikace (SPA). Zjistěte, jak vytvořit aplikaci SPA pomocí knihovny Microsoft Authentication Library pro JavaScript (MSAL.js).

Tento článek použijte s konfigurací ověřování v ukázkové aplikaci SPA a nahraďte ukázkovou aplikaci SPA vlastní aplikací SPA.

Přehled

Tento článek používá Node.js a Express k vytvoření základní webové aplikace Node.js. Express je minimální a flexibilní architektura webové aplikace Node.js, která poskytuje sadu funkcí pro webové a mobilní aplikace.

Knihovna MSAL.js pro autentizaci od společnosti Microsoft je knihovna, která zjednodušuje přidání podpory autentizace a autorizace do aplikací SPA.

Návod

Celý kód MSAL.js běží na straně klienta. Kód na straně serveru Node.js a Express můžete nahradit jinými řešeními, jako jsou skriptovací jazyky .NET Core, Java a Hypertext Preprocessor (PHP).

Požadavky

Pokud chcete zkontrolovat požadavky a pokyny k integraci, přečtěte si téma Konfigurace ověřování v ukázkové aplikaci SPA.

Krok 1: Vytvoření projektu aplikace SPA

Můžete použít existující projekt aplikace SPA nebo vytvořit nový. Pokud chcete vytvořit nový projekt, postupujte takto:

  1. Otevřete příkazové prostředí a vytvořte nový adresář (například myApp). Tento adresář bude obsahovat kód aplikace, uživatelské rozhraní a konfigurační soubory.

  2. Zadejte adresář, který jste vytvořili.

  3. npm init Pomocí příkazu vytvořte package.json soubor pro vaši aplikaci. Tento příkaz vás vyzve k zadání informací o vaší aplikaci (například název a verzi aplikace a název počátečního vstupního bodu, souboru index.js ). Spusťte následující příkaz a přijměte výchozí hodnoty:

npm init

Krok 2: Instalace závislostí

Pokud chcete nainstalovat balíček Express, spusťte v příkazovém prostředí následující příkaz:

npm install express

K vyhledání statických souborů aplikace používá kód na straně serveru balíček Cesta .

Pokud chcete nainstalovat balíček Path, spusťte v příkazovém prostředí následující příkaz:

npm install path

Krok 3: Konfigurace webového serveru

Ve složce myApp vytvořte soubor s názvem index.js, který obsahuje následující kód:

// Initialize express
const express = require('express');
const app = express();

// The port to listen to incoming HTTP requests
const port = 6420;

// Initialize path
const path = require('path');

// Set the front-end folder to serve public assets.
app.use(express.static('App'));

// Set up a route for the index.html
app.get('*', (req, res) => {
    res.sendFile(path.join(__dirname + '/index.html'));
});

// Start the server, and listen for HTTP requests
app.listen(port, () => {
  console.log(`Listening on http://localhost:${port}`);
});

Krok 4: Vytvoření uživatelského rozhraní SPA

Přidejte soubor aplikace index.html SPA. Tento soubor implementuje uživatelské rozhraní vytvořené pomocí architektury Bootstrap a importuje soubory skriptů pro konfiguraci, ověřování a volání webového rozhraní API.

Prostředky, na které soubor index.html odkazuje, jsou podrobně popsány v následující tabulce:

Odkazy Definice
MSAL.js knihovna MSAL.js autentizační knihovna JavaScript Cesta CDN.
Šablona stylů Bootstrap Bezplatná front-endová architektura pro rychlejší a jednodušší vývoj webů. Tato architektura zahrnuje šablony návrhu založené na HTML a CSS.

Chcete-li vykreslit soubor indexu SPA, vytvořte ve složce myApp soubor s názvem index.html, který obsahuje následující fragment kódu HTML:

<!DOCTYPE html>
<html>
    <head>
        <title>My Azure AD B2C test app</title>
    </head>
    <body>
        <h2>My Azure AD B2C test app</h2>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" />
        <button type="button" id="signIn" class="btn btn-secondary" onclick="signIn()">Sign-in</button>
        <button type="button" id="signOut" class="btn btn-success d-none" onclick="signOut()">Sign-out</button>
        <h5 id="welcome-div" class="card-header text-center d-none"></h5>
        <br />
        <!-- Content -->
        <div class="card">
            <div class="card-body text-center">
                <pre id="response" class="card-text"></pre>
                <button type="button" id="callApiButton" class="btn btn-primary d-none" onclick="passTokenToApi()">Call API</button>
            </div>
        </div>
        <script src="https://alcdn.msauth.net/browser/2.14.2/js/msal-browser.min.js" integrity="sha384-ggh+EF1aSqm+Y4yvv2n17KpurNcZTeYtUZUvhPziElsstmIEubyEB6AIVpKLuZgr" crossorigin="anonymous"></script>

        <!-- Importing app scripts (load order is important) -->
        <script type="text/javascript" src="./apiConfig.js"></script>
        <script type="text/javascript" src="./policies.js"></script>
        <script type="text/javascript" src="./authConfig.js"></script>
        <script type="text/javascript" src="./ui.js"></script>

        <!-- <script type="text/javascript" src="./authRedirect.js"></script>   -->
        <!-- uncomment the above line and comment the line below if you would like to use the redirect flow -->
        <script type="text/javascript" src="./authRedirect.js"></script>
        <script type="text/javascript" src="./api.js"></script>
    </body>
</html>

Krok 5: Konfigurace knihovny ověřování

Nakonfigurujte, jak se knihovna MSAL.js integruje s Azure AD B2C. Knihovna MSAL.js používá standardní konfigurační objekt pro připojení ke koncovým bodům ověřování klienta Azure AD B2C.

Pokud chcete nakonfigurovat knihovnu ověřování, postupujte takto:

  1. Ve složce myApp vytvořte novou složku s názvem Aplikace.

  2. Ve složce Aplikace vytvořte nový soubor s názvem authConfig.js.

  3. Do souboru authConfig.js přidejte následující kód JavaScript:

    const msalConfig = {
        auth: {
        clientId: "<Application-ID>", 
        authority: b2cPolicies.authorities.signUpSignIn.authority, 
        knownAuthorities: [b2cPolicies.authorityDomain], 
        redirectUri: "http://localhost:6420",
        },
        cache: {
        cacheLocation: "localStorage", .
        storeAuthStateInCookie: false, 
        }
    };
    
    const loginRequest = {
    scopes: ["openid", ...apiConfig.b2cScopes],
    };
    
    const tokenRequest = {
    scopes: [...apiConfig.b2cScopes],
    forceRefresh: false
    };
    
  4. Nahraďte <Application-ID> ID aplikace pro registraci aplikace. Další informace najdete v tématu Konfigurace ověřování v ukázkové aplikaci SPA.

Návod

Další možnosti konfigurace objektů MSAL najdete v článku Možnosti ověřování .

Krok 6: Určení toků uživatelů Azure AD B2C

Vytvořte soubor policies.js , který poskytuje informace o vašem prostředí Azure AD B2C. Knihovna MSAL.js používá tyto informace k vytváření žádostí o ověření pro Azure AD B2C.

Pokud chcete zadat toky uživatelů Azure AD B2C, postupujte takto:

  1. Ve složce Aplikace vytvořte nový soubor s názvem policies.js.

  2. Do souboru policies.js přidejte následující kód:

    const b2cPolicies = {
        names: {
            signUpSignIn: "B2C_1_SUSI",
            editProfile: "B2C_1_EditProfile"
        },
        authorities: {
            signUpSignIn: {
                authority: "https://contoso.b2clogin.com/contoso.onmicrosoft.com/Your-B2C-SignInOrSignUp-Policy-Id",
            },
            editProfile: {
                authority: "https://contoso.b2clogin.com/contoso.onmicrosoft.com/Your-B2C-EditProfile-Policy-Id"
            }
        },
        authorityDomain: "contoso.b2clogin.com"
    }
    
  3. Nahraďte B2C_1_SUSI názvem zásady Azure AD B2C pro přihlášení.

  4. Nahraďte B2C_1_EditProfile názvem zásady úprav profilu Azure AD B2C.

  5. Nahraďte všechny instance contoso názvem vašeho tenanta Azure AD B2C.

Krok 7: Přihlášení uživatele pomocí knihovny MSAL

V tomto kroku implementujte metody inicializace toku přihlašování, získání přístupového tokenu rozhraní API a metod odhlášení.

Další informace naleznete v článku Použití knihovny Microsoft Authentication Library (MSAL) k přihlášení uživatele.

Pokud se chcete přihlásit uživatele, postupujte takto:

  1. Ve složce Aplikace vytvořte nový soubor s názvem authRedirect.js.

  2. V authRedirect.jszkopírujte a vložte následující kód:

    // Create the main myMSALObj instance
    // configuration parameters are located at authConfig.js
    const myMSALObj = new msal.PublicClientApplication(msalConfig);
    
    let accountId = "";
    let idTokenObject = "";
    let accessToken = null;
    
    myMSALObj.handleRedirectPromise()
        .then(response => {
            if (response) {
                /**
                 * For the purpose of setting an active account for UI update, we want to consider only the auth response resulting
                 * from SUSI flow. "tfp" claim in the id token tells us the policy (NOTE: legacy policies may use "acr" instead of "tfp").
                 * To learn more about B2C tokens, visit https://learn.microsoft.com/azure/active-directory-b2c/tokens-overview
                 */
                if (response.idTokenClaims['tfp'].toUpperCase() === b2cPolicies.names.signUpSignIn.toUpperCase()) {
                    handleResponse(response);
                }
            }
        })
        .catch(error => {
            console.log(error);
        });
    
    
    function setAccount(account) {
        accountId = account.homeAccountId;
        idTokenObject = account.idTokenClaims;
        myClaims= JSON.stringify(idTokenObject);
        welcomeUser(myClaims);
    }
    
    function selectAccount() {
    
        /**
         * See here for more information 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.length < 1) {
            return;
        } else if (currentAccounts.length > 1) {
    
            /**
             * Due to the way MSAL caches account objects, the auth response from initiating a user-flow
             * is cached as a new account, which results in more than one account in the cache. Here we make
             * sure we are selecting the account with homeAccountId that contains the sign-up/sign-in user-flow, 
             * as this is the default flow the user initially signed-in with.
             */
            const accounts = currentAccounts.filter(account =>
                account.homeAccountId.toUpperCase().includes(b2cPolicies.names.signUpSignIn.toUpperCase())
                &&
                account.idTokenClaims.iss.toUpperCase().includes(b2cPolicies.authorityDomain.toUpperCase())
                &&
                account.idTokenClaims.aud === msalConfig.auth.clientId 
                );
    
            if (accounts.length > 1) {
                // localAccountId identifies the entity for which the token asserts information.
                if (accounts.every(account => account.localAccountId === accounts[0].localAccountId)) {
                    // All accounts belong to the same user
                    setAccount(accounts[0]);
                } else {
                    // Multiple users detected. Logout all to be safe.
                    signOut();
                };
            } else if (accounts.length === 1) {
                setAccount(accounts[0]);
            }
    
        } else if (currentAccounts.length === 1) {
            setAccount(currentAccounts[0]);
        }
    }
    
    // in case of page refresh
    selectAccount();
    
    async function handleResponse(response) {
    
        if (response !== null) {
            setAccount(response.account);
        } else {
            selectAccount();
        }
    }
    
    function signIn() {
        myMSALObj.loginRedirect(loginRequest);
    }
    
    function signOut() {
        const logoutRequest = {
            postLogoutRedirectUri: msalConfig.auth.redirectUri,
        };
    
        myMSALObj.logoutRedirect(logoutRequest);
    }
    
    function getTokenRedirect(request) {
        request.account = myMSALObj.getAccountByHomeId(accountId); 
    
        return myMSALObj.acquireTokenSilent(request)
            .then((response) => {
                // In case the response from B2C server has an empty accessToken field
                // throw an error to initiate token acquisition
                if (!response.accessToken || response.accessToken === "") {
                    throw new msal.InteractionRequiredAuthError;
                } else {
                    console.log("access_token acquired at: " + new Date().toString());
                    accessToken = response.accessToken;
                    passTokenToApi();
                }
            }).catch(error => {
                console.log("Silent token acquisition fails. Acquiring token using popup. \n", error);
                if (error instanceof msal.InteractionRequiredAuthError) {
                    // fallback to interaction when silent call fails
                    return myMSALObj.acquireTokenRedirect(request);
                } else {
                    console.log(error);   
                }
        });
    }
    
    // Acquires and access token and then passes it to the API call
    function passTokenToApi() {
        if (!accessToken) {
            getTokenRedirect(tokenRequest);
        } else {
            try {
                callApi(apiConfig.webApi, accessToken);
            } catch(error) {
                console.log(error); 
            }
        }
    }
    
    function editProfile() {
    
    
        const editProfileRequest = b2cPolicies.authorities.editProfile;
        editProfileRequest.loginHint = myMSALObj.getAccountByHomeId(accountId).username;
    
        myMSALObj.loginRedirect(editProfileRequest);
    }
    

Krok 8: Konfigurace umístění a oboru webového rozhraní API

Pokud chcete aplikaci SPA povolit volání webového rozhraní API, zadejte umístění koncového bodu webového rozhraní API a rozsahy , které se mají použít k autorizaci přístupu k webovému rozhraní API.

Pokud chcete nakonfigurovat umístění a obory webového rozhraní API, postupujte takto:

  1. Ve složce Aplikace vytvořte nový soubor s názvem apiConfig.js.

  2. V apiConfig.jszkopírujte a vložte následující kód:

    // The current application coordinates were pre-registered in a B2C tenant.
    const apiConfig = {
        b2cScopes: ["https://contoso.onmicrosoft.com/tasks/tasks.read"],
        webApi: "https://mydomain.azurewebsites.net/tasks"
    };
    
  3. Nahraďte contoso názvem vašeho tenanta. Požadovaný název oboru najdete podle popisu v článku Konfigurace oborů .

  4. Nahraďte hodnotu webApi umístěním koncového bodu webového rozhraní API.

Krok 9: Volání webového rozhraní API

Definujte požadavek HTTP na koncový bod rozhraní API. Požadavek HTTP je nakonfigurován tak, aby předal přístupový token, který byl získán pomocí MSAL.js , do hlavičky Authorization HTTP v požadavku.

Následující kód definuje požadavek HTTP GET na koncový bod rozhraní API a předá přístupový token v Authorization hlavičce HTTP. Umístění rozhraní API je definováno webApi klíčem v apiConfig.js.

Pokud chcete volat webové rozhraní API pomocí tokenu, který jste získali, postupujte takto:

  1. Ve složce Aplikace vytvořte nový soubor s názvem api.js.

  2. Do souboru api.js přidejte následující kód:

    function callApi(endpoint, token) {
    
        const headers = new Headers();
        const bearer = `Bearer ${token}`;
    
        headers.append("Authorization", bearer);
    
        const options = {
            method: "GET",
            headers: headers
        };
    
        logMessage('Calling web API...');
    
        fetch(endpoint, options)
        .then(response => response.json())
        .then(response => {
    
            if (response) {
            logMessage('Web API responded: ' + response.name);
            }
    
            return response;
        }).catch(error => {
            console.error(error);
        });
    }
    

Krok 10: Přidání odkazu na prvky uživatelského rozhraní

Aplikace SPA používá JavaScript k řízení prvků uživatelského rozhraní. Zobrazí například tlačítka pro přihlášení a odhlášení a vykreslí deklarace identity tokenu ID uživatele na obrazovku.

Pokud chcete přidat referenční informace k prvkům uživatelského rozhraní, postupujte takto:

  1. Ve složce Aplikace vytvořte soubor s názvem ui.js.

  2. Do souboru ui.js přidejte následující kód:

    // 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');
    const editProfileButton = document.getElementById('editProfileButton');
    const callApiButton = document.getElementById('callApiButton');
    const response = document.getElementById("response");
    const label = document.getElementById('label');
    
    function welcomeUser(claims) {
        welcomeDiv.innerHTML = `Token claims: </br></br> ${claims}!`
    
        signInButton.classList.add('d-none');
        signOutButton.classList.remove('d-none');
        welcomeDiv.classList.remove('d-none');
        callApiButton.classList.remove('d-none');
    }
    
    function logMessage(s) {
        response.appendChild(document.createTextNode('\n' + s + '\n'));
    }
    

Krok 11: Spuštění aplikace SPA

V příkazovém prostředí spusťte následující příkazy:

npm install  
npm ./index.js
  1. Přejít na https://localhost:6420.
  2. Vyberte Přihlásit se.
  3. Dokončete proces registrace nebo přihlášení.

Po úspěšném ověření se na obrazovce zobrazí token parsovaného ID. Vyberte Call API a zavolejte koncový bod API.

Další kroky