Share via


Verificatie inschakelen in uw eigen toepassing met één pagina met behulp van Azure AD B2C

In dit artikel wordt beschreven hoe u Azure Active Directory B2C-verificatie (Azure AD B2C) toevoegt aan uw eigen toepassing met één pagina (SPA). Meer informatie over het maken van een beveiligd-WACHTWOORDVERIFICATIE-toepassing met behulp van de Microsoft Authentication Library voor JavaScript (MSAL.js).

Gebruik dit artikel met Verificatie configureren in een voorbeeld-BEVEILIGD-WACHTWOORDVERIFICATIE-toepassing, waarbij u de voorbeeld-BEVEILIGD-app vervangt door uw eigen beveiligd-WACHTWOORDVERIFICATIE-app.

Overzicht

In dit artikel worden Node.js en Express gebruikt om een eenvoudige Node.js web-app te maken. Express is een minimaal en flexibel Node.js web-app-framework dat een set functies biedt voor web- en mobiele toepassingen.

De MSAL.js verificatiebibliotheek is een door Microsoft geleverde bibliotheek die het toevoegen van verificatie- en autorisatieondersteuning aan beveiligd-WACHTWOORDVERIFICATIE-apps vereenvoudigt.

Tip

De volledige MSAL.js code wordt uitgevoerd aan de clientzijde. U kunt de code aan de Node.js- en Express-serverzijde vervangen door andere oplossingen, zoals .NET Core, Java en PHP-scripttalen (Hypertext Preprocessor).

Vereisten

Zie Verificatie configureren in een voorbeeld-BEVEILIGD-WACHTWOORDVERIFICATIE-toepassing om de vereisten en integratie-instructies te bekijken.

Stap 1: Een beveiligd-WACHTWOORDVERIFICATIE-app-project maken

U kunt een bestaand beveiligd-WACHTWOORDVERIFICATIE-app-project gebruiken of een nieuw maken. Ga als volgt te werk om een nieuw project te maken:

  1. Open een opdrachtshell en maak een nieuwe map (bijvoorbeeld myApp). Deze map bevat uw app-code, gebruikersinterface en configuratiebestanden.

  2. Voer de map in die u hebt gemaakt.

  3. Gebruik de npm init opdracht om een package.json bestand voor uw app te maken. Met deze opdracht wordt u gevraagd om informatie over uw app (bijvoorbeeld de naam en versie van uw app en de naam van het oorspronkelijke toegangspunt, het index.js-bestand ). Voer de volgende opdracht uit en accepteer de standaardwaarden:

npm init

Stap 2: De afhankelijkheden installeren

Als u het Express-pakket wilt installeren, voert u de volgende opdracht uit in de opdrachtshell:

npm install express

Om de statische bestanden van de app te vinden, gebruikt de code aan de serverzijde het Pad-pakket .

Als u het Pad-pakket wilt installeren, voert u in de opdrachtshell de volgende opdracht uit:

npm install path

Stap 3: uw webserver configureren

Maak in de map myApp een bestand met de naam index.js, dat de volgende code bevat:

// 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}`);
});

Stap 4: de gebruikersinterface voor beveiligd-WACHTWOORDVERIFICATIE maken

Voeg het beveiligd-WACHTWOORDVERIFICATIE-app-bestand index.html toe. Dit bestand implementeert een gebruikersinterface die is gebouwd met een Bootstrap-framework en importeert scriptbestanden voor configuratie, verificatie en web-API-aanroepen.

De resources waarnaar wordt verwezen door het index.html-bestand , worden beschreven in de volgende tabel:

Referentie Definitie
MSAL.js bibliotheek MSAL.js het CDN-pad van de JavaScript-bibliotheek voor verificatie.
Bootstrap-opmaakmodel Een gratis front-endframework voor snellere en eenvoudigere webontwikkeling. Het framework bevat ontwerpsjablonen op basis van HTML en CSS.
policies.js Bevat de Azure AD aangepastE B2C-beleidsregels en gebruikersstromen.
authConfig.js Bevat configuratieparameters voor verificatie.
authRedirect.js Bevat de verificatielogica.
apiConfig.js Bevat web-API-bereiken en de locatie van het API-eindpunt.
api.js Definieert de methode die moet worden gebruikt om uw API aan te roepen en het antwoord ervan af te handelen.
ui.js Hiermee bepaalt u de elementen van de gebruikersinterface.

Als u het beveiligd-WACHTWOORDVERIFICATIE-indexbestand wilt weergeven, maakt u in de map myApp een bestand met de naam index.html, dat het volgende HTML-fragment bevat:

<!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>

Stap 5: de verificatiebibliotheek configureren

Configureer hoe de MSAL.js-bibliotheek kan worden geïntegreerd met Azure AD B2C. De MSAL.js-bibliotheek maakt gebruik van een gemeenschappelijk configuratieobject om verbinding te maken met de verificatie-eindpunten van uw Azure AD B2C-tenant.

Ga als volgt te werk om de verificatiebibliotheek te configureren:

  1. Maak in de map myApp een nieuwe map met de naam App.

  2. Maak in de map App een nieuw bestand met de naam authConfig.js.

  3. Voeg de volgende JavaScript-code toe aan het authConfig.js-bestand :

    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. Vervang door de toepassings-id <Application-ID> van uw app-registratie. Zie Verificatie configureren in een voorbeeld-BEVEILIGD-WACHTWOORDVERIFICATIE-toepassing voor meer informatie.

Tip

Zie het artikel Verificatieopties voor meer configuratieopties voor MSAL-objecten .

Stap 6: geef uw Azure AD B2C-gebruikersstromen op

Maak het policies.js-bestand met informatie over uw Azure AD B2C-omgeving. De MSAL.js-bibliotheek gebruikt deze informatie om verificatieaanvragen te maken voor Azure AD B2C.

Ga als volgt te werk om uw Azure AD B2C-gebruikersstromen op te geven:

  1. Maak in de map App een nieuw bestand met de naam policies.js.

  2. Voeg de volgende code toe aan het policies.js-bestand :

    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. Vervang door B2C_1_SUSI uw aanmeldingsnaam Azure AD B2C-beleid.

  4. Vervang door B2C_1_EditProfile uw bewerkingsprofiel Azure AD naam van het B2C-beleid.

  5. Vervang alle exemplaren van door de naam van contoso uw Azure AD B2C-tenant.

Stap 7: de MSAL gebruiken om de gebruiker aan te melden

In deze stap implementeert u de methoden voor het initialiseren van de aanmeldingsstroom, het verkrijgen van API-toegangstokens en de afmeldingsmethoden.

Zie het artikel Use the Microsoft Authentication Library (MSAL) to sign in the user (De Microsoft Authentication Library (MSAL) gebruiken om de gebruiker aan te melden voor meer informatie.

Ga als volgt te werk om de gebruiker aan te melden:

  1. Maak in de map App een nieuw bestand met de naam authRedirect.js.

  2. Kopieer en plak de volgende code in uw authRedirect.js:

    // 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);
    }
    

Stap 8: de locatie en het bereik van de web-API configureren

Als u wilt dat uw beveiligd-WACHTWOORDVERIFICATIE-app een web-API aanroept, geeft u de eindpuntlocatie van de web-API en de bereiken op die moeten worden gebruikt om toegang tot de web-API te autoriseren.

Ga als volgt te werk om de locatie en bereiken van de web-API te configureren:

  1. Maak in de map App een nieuw bestand met de naam apiConfig.js.

  2. Kopieer en plak de volgende code in uw apiConfig.js:

    // 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. Vervang door contoso de naam van uw tenant. De vereiste bereiknaam vindt u zoals beschreven in het artikel Bereiken configureren .

  4. Vervang de waarde voor door webApi de locatie van uw web-API-eindpunt.

Stap 9: uw web-API aanroepen

Definieer de HTTP-aanvraag voor uw API-eindpunt. De HTTP-aanvraag is geconfigureerd om het toegangstoken dat is verkregen met MSAL.js door te geven aan de Authorization HTTP-header in de aanvraag.

De volgende code definieert de HTTP-aanvraag GET naar het API-eindpunt, waarbij het toegangstoken binnen de Authorization HTTP-header wordt doorgegeven. De API-locatie wordt gedefinieerd door de webApi sleutel in apiConfig.js.

Ga als volgt te werk om uw web-API aan te roepen met behulp van het token dat u hebt verkregen:

  1. Maak in de map App een nieuw bestand met de naam api.js.

  2. Voeg de volgende code toe aan het api.js-bestand :

    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);
        });
    }
    

Stap 10: De verwijzing naar ui-elementen toevoegen

De beveiligd-WACHTWOORDVERIFICATIE-app gebruikt JavaScript om de elementen van de gebruikersinterface te beheren. Zo worden bijvoorbeeld de knoppen voor aanmelden en afmelden weergegeven en worden de id-tokenclaims van de gebruiker weergegeven op het scherm.

Ga als volgt te werk om de verwijzing naar ui-elementen toe te voegen:

  1. Maak in de map App een bestand met de naam ui.js.

  2. Voeg de volgende code toe aan het ui.js-bestand :

    // 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'));
    }
    

Stap 11: De toepassing beveiligd-WACHTWOORDVERIFICATIE uitvoeren

Voer in de opdrachtshell de volgende opdrachten uit:

npm install  
npm ./index.js
  1. Ga naar https://localhost:6420.
  2. Selecteer Aanmelden.
  3. Voltooi het aanmeldings- of registratieproces.

Nadat u zich hebt geverifieerd, wordt het geparseerde id-token weergegeven op het scherm. Selecteer Call API om uw API-eindpunt aan te roepen.

Volgende stappen