Verificatie inschakelen in uw eigen Node.js-web-API met behulp van Azure Active Directory B2C

In dit artikel leert u hoe u uw web-app maakt die uw web-API aanroept. De web-API moet worden beveiligd door Azure Active Directory B2C (Azure AD B2C). Als u toegang wilt verlenen tot een web-API, dient u aanvragen in met een geldig toegangstoken dat is uitgegeven door Azure AD B2C.

Vereisten

Stap 1: Een beveiligde web-API maken

Volg deze stappen om uw web-API voor Node.js te maken.

Stap 1.1: Het project maken

Gebruik Express om met Node.js een web-API te compileren. Ga als volgt te werk om een web-API te maken:

  1. Maak een nieuwe map met de naam TodoList.
  2. Maak in de map TodoList een bestand met de naam index.js.
  3. Voer in de opdrachtshell npm init -y uit. Met deze opdracht maakt u een package.json-standaardbestand voor uw Node.js-project.
  4. Voer in de opdrachtshell npm install express uit. Met deze opdracht wordt het Express-framework geïnstalleerd.

Stap 1.2: Afhankelijkheden installeren

Voeg de verificatiebibliotheek toe aan uw web-API-project. De verificatiebibliotheek parseert de HTTP-verificatieheader, valideert het token en extraheert claims. Raadpleeg de documentatie voor de bibliotheek voor meer informatie.

Als u de verificatiebibliotheek wilt toevoegen, installeert u de pakketten door de volgende opdracht uit te voeren:

npm install passport
npm install passport-azure-ad
npm install morgan

Het morgan-pakket is logger-middleware voor HTTP-aanvragen voor Node.js.

Stap 1.3: De code van de web-API-server schrijven

Voeg in het bestand index.js de volgende code toe:

const express = require('express');
const morgan = require('morgan');
const passport = require('passport');
const config = require('./config.json');
const todolist = require('./todolist');
const cors = require('cors');

//<ms_docref_import_azuread_lib>
const BearerStrategy = require('passport-azure-ad').BearerStrategy;
//</ms_docref_import_azuread_lib>

global.global_todos = [];

//<ms_docref_azureadb2c_options>
const options = {
    identityMetadata: `https://${config.credentials.tenantName}.b2clogin.com/${config.credentials.tenantName}.onmicrosoft.com/${config.policies.policyName}/${config.metadata.version}/${config.metadata.discovery}`,
    clientID: config.credentials.clientID,
    audience: config.credentials.clientID,
    policyName: config.policies.policyName,
    isB2C: config.settings.isB2C,
    validateIssuer: config.settings.validateIssuer,
    loggingLevel: config.settings.loggingLevel,
    passReqToCallback: config.settings.passReqToCallback
}

//</ms_docref_azureadb2c_options>

//<ms_docref_init_azuread_lib>
const bearerStrategy = new BearerStrategy(options, (token, done) => {
        // Send user info using the second argument
        done(null, { }, token);
    }
);
//</ms_docref_init_azuread_lib>
const app = express();

app.use(express.json()); 

//enable CORS (for testing only -remove in production/deployment)
app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Authorization, Origin, X-Requested-With, Content-Type, Accept');
    next();
});

app.use(morgan('dev'));

app.use(passport.initialize());

passport.use(bearerStrategy);

// To do list endpoints
app.use('/api/todolist', todolist);

//<ms_docref_protected_api_endpoint>
// API endpoint, one must present a bearer accessToken to access this endpoint
app.get('/hello',
    passport.authenticate('oauth-bearer', {session: false}),
    (req, res) => {
        console.log('Validated claims: ', req.authInfo);
    
          
        // Service relies on the name claim.  
        res.status(200).json({'name': req.authInfo['name']});
    }
);
//</ms_docref_protected_api_endpoint>

//<ms_docref_anonymous_api_endpoint>
// API anonymous endpoint, returns a date to the caller.
app.get('/public', (req, res) => res.send( {'date': new Date() } ));
//</ms_docref_anonymous_api_endpoint>

const port = process.env.PORT || 5000;

app.listen(port, () => {
    console.log('Listening on port ' + port);
});

Noteer de volgende codefragmenten in het index.jsbestand:

  • Importeert de Azure AD-bibliotheek van het paspoort

    const BearerStrategy = require('passport-azure-ad').BearerStrategy;
    
  • Hiermee stelt u de Azure AD B2C-opties in

    const options = {
        identityMetadata: `https://${config.credentials.tenantName}.b2clogin.com/${config.credentials.tenantName}.onmicrosoft.com/${config.policies.policyName}/${config.metadata.version}/${config.metadata.discovery}`,
        clientID: config.credentials.clientID,
        audience: config.credentials.clientID,
        policyName: config.policies.policyName,
        isB2C: config.settings.isB2C,
        validateIssuer: config.settings.validateIssuer,
        loggingLevel: config.settings.loggingLevel,
        passReqToCallback: config.settings.passReqToCallback
    }
    
  • Instantieer het paspoort Azure AD bibliotheek met de Azure AD B2C-opties

    const bearerStrategy = new BearerStrategy(options, (token, done) => {
            // Send user info using the second argument
            done(null, { }, token);
        }
    );
    
  • Het beveiligde API-eindpunt. Het dient aanvragen in met een geldig door Azure AD-B2C uitgegeven toegangstoken. Dit eindpunt retourneert de waarde van de name-claim in het toegangstoken.

    // API endpoint, one must present a bearer accessToken to access this endpoint
    app.get('/hello',
        passport.authenticate('oauth-bearer', {session: false}),
        (req, res) => {
            console.log('Validated claims: ', req.authInfo);
        
              
            // Service relies on the name claim.  
            res.status(200).json({'name': req.authInfo['name']});
        }
    );
    
  • Het anonieme API-eindpunt. De web-app kan deze aanroepen zonder een toegangstoken te presenteren. Gebruik het om fouten in uw web-API op te sporen met anonieme aanroepen.

    // API anonymous endpoint, returns a date to the caller.
    app.get('/public', (req, res) => res.send( {'date': new Date() } ));
    

Stap 1.4: De web-API configureren

Voeg configuraties toe aan een configuratiebestand. Het bestand bevat informatie over uw Azure AD B2C-id-provider. De web-API-app gebruikt deze informatie om het toegangstoken te valideren dat de web-app als Bearer-token doorgeeft.

  1. Maak in de hoofdmap van het project een config.json-bestand en voeg er vervolgens het volgende JSON-object aan toe:

    {
        "credentials": {
            "tenantName": "fabrikamb2c",
            "clientID": "93733604-cc77-4a3c-a604-87084dd55348"
        },
        "policies": {
            "policyName": "B2C_1_susi"
        },
        "resource": {
            "scope": ["tasks.read"]
        },
        "metadata": {
            "authority": "login.microsoftonline.com",
            "discovery": ".well-known/openid-configuration",
            "version": "v2.0"
        },
        "settings": {
            "isB2C": true,
            "validateIssuer": true,
            "passReqToCallback": false,
            "loggingLevel": "info"
        }
    }
    
  2. Werk in het bestand config.json de volgende eigenschappen bij:

Sectie Sleutel Waarde
referenties tenantName Het eerste deel van uw Azure AD B2C-tenantnaam (bijvoorbeeld fabrikamb2c).
referenties clientID De id van de web-API-toepassing. Zie Vereisten voor meer informatie over het ophalen van de registratie-id van uw web-API-toepassing.
policies policyName De gebruikersstromen of het aangepaste beleid. Zie Vereisten voor meer informatie over het verkrijgen van uw gebruikersstroom of beleid.
resource scope De bereiken van de registratie van uw web-API-toepassing, zoals [tasks.read]. Zie Vereisten voor meer informatie over het verkrijgen van uw web-API-bereik.

Stap 2: De webtoepassing voor het web-Node maken

Volg deze stappen om de Node-web-app te maken. Deze web-app verifieert een gebruiker om een toegangstoken te verkrijgen dat wordt gebruikt om de Node-web-API aan te roepen die u in stap 1 hebt gemaakt:

Stap 2.1: Het knooppuntproject maken

Maak een map voor het opslaan van uw knooppunttoepassing, zoals call-protected-api.

  1. Wijzig in uw terminal de map in uw knooppunttoepassingsmap, zoals cd call-protected-api, en voer npm init -y uit. Met deze opdracht maakt u een package.json-standaardbestand voor uw Node.js-project.

  2. Voer npm install express uit in uw terminal. Met deze opdracht wordt het Express-framework geïnstalleerd.

  3. Maak meer mappen en bestanden om de volgende projectstructuur te bereiken:

    call-protected-api/
    ├── index.js
    └── package.json
    └── .env
    └── views/
        └── layouts/
            └── main.hbs
        └── signin.hbs
        └── api.hbs
    

    De map views bevat handlebars-bestanden voor de gebruikersinterface van de web-app.

Stap 2.2: De afhankelijkheden installeren

Installeer in uw terminal de pakketten dotenv, express-handlebars, express-session en @azure/msal-node door de volgende opdrachten uit te voeren:

npm install dotenv
npm install express-handlebars
npm install express
npm install axios
npm install express-session
npm install @azure/msal-node

Stap 2.3: Onderdelen van de web-app-gebruikersinterface bouwen

  1. Voeg in het bestand main.hbs de volgende code toe:

    <!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>Azure AD B2C | Enable authenticate on web API using MSAL for B2C</title>
    
        <!-- adding Bootstrap 4 for UI components  -->
        <!-- CSS only -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
        <link rel="SHORTCUT ICON" href="https://c.s-microsoft.com/favicon.ico?v2" type="image/x-icon">
      </head>
      <body>
        <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
          <a class="navbar-brand" href="/">Microsoft Identity Platform</a>
            {{#if showSignInButton}}
                <div class="ml-auto">
                    <a type="button" id="SignIn" class="btn btn-success" href="/signin" aria-haspopup="true" aria-expanded="false">
                        Sign in to call PROTECTED API
                    </a>
                    <a type="button" id="SignIn" class="btn btn-warning" href="/api" aria-haspopup="true" aria-expanded="false">
                        Or call the ANONYMOUS API 
                     </a>
                </div>
            {{else}}
                    <p class="navbar-brand d-flex ms-auto">Hi {{givenName}}</p>
                    <a class="navbar-brand d-flex ms-auto" href="/signout">Sign out</a>
            {{/if}}
        </nav>
        <br>
        <h5 class="card-header text-center">MSAL Node Confidential Client application with Auth Code Flow</h5>
        <br>
        <div class="row" style="margin:auto" >
          {{{body}}}
        </div>
        <br>
        <br>
      </body>
    </html>
    

    Het bestand main.hbs bevindt zich in de map layout en moet HTML-code bevatten die in uw toepassing is vereist. Het implementeert de gebruikersinterface die is gebouwd met het Bootstrap 5 CSS Framework. Elke gebruikersinterface die van pagina naar pagina verandert, zoals signin.hbs, wordt in de tijdelijke aanduiding geplaatst die wordt weergegeven als {{{body}}}.

  2. Voeg in het bestand signin.hbs de volgende code toe:

    <div class="col-md-3" style="margin:auto">
      <div class="card text-center">
        <div class="card-body">
          {{#if showSignInButton}}
    
          {{else}}
               <h5 class="card-title">You have signed in</h5>
              <a type="button" id="Call-api" class="btn btn-success" href="/api" aria-haspopup="true" aria-expanded="false">
                  Call the PROTECTED API
              </a>
          {{/if}}
        </div>
        </div>
      </div>
    </div>
    
  3. Voeg in het bestand api.hbs de volgende code toe:

    <div class="col-md-3" style="margin:auto">
      <div class="card text-center bg-{{bg_color}}">
        <div class="card-body">
    
              <h5 class="card-title">{{data}}</h5>
    
        </div>
      </div>
    </div>
    

    Op deze pagina wordt het antwoord van de API weergegeven. Met het bg-{{bg_color}}-klassekenmerk in de bootstrap-kaart kan de gebruikersinterface een andere achtergrondkleur voor de verschillende API-eindpunten weergeven.

Stap 2.4: Volledige code van de webtoepassingsserver

  1. Voeg in het bestand .env de volgende code toe, met daarin de http-poort van de server, details van app-registratie en de gebruikersstroom/beleidsdetails voor het aanmelden en registreren:

    SERVER_PORT=3000
    #web apps client ID
    APP_CLIENT_ID=<You app client ID here>
    #session secret
    SESSION_SECRET=sessionSecretHere
    #web app client secret
    APP_CLIENT_SECRET=<Your app client secret here>
    #tenant name
    TENANT_NAME=<your-tenant-name>
    #B2C sign up and sign in user flow/policy name and authority
    SIGN_UP_SIGN_IN_POLICY_AUTHORITY=https://<your-tenant-name>.b2clogin.com/<your-tenant-name>.onmicrosoft.com/<sign-in-sign-up-user-flow-name>
    AUTHORITY_DOMAIN=https://<your-tenant-name>.b2clogin.com
    #client redorect url
    APP_REDIRECT_URI=http://localhost:3000/redirect
    LOGOUT_ENDPOINT=https://<your-tenant-name>.b2clogin.com/<your-tenant-name>.onmicrosoft.com/<sign-in-sign-up-user-flow-name>/oauth2/v2.0/logout?post_logout_redirect_uri=http://localhost:3000
    

    Wijzig de waarden in de .env-bestanden zoals uitgelegd in De voorbeeldweb-app configureren

  2. Voeg in uw bestand index.js de volgende code toe:

    /*
     * Copyright (c) Microsoft Corporation. All rights reserved.
     * Licensed under the MIT License.
     */
    require('dotenv').config();
    const express = require('express');
    const session = require('express-session');
    const {engine}  = require('express-handlebars');
    const msal = require('@azure/msal-node');
    //Use axios to make http calls 
    const axios = require('axios');
    
    //<ms_docref_configure_msal>
    /**
     * Confidential Client Application Configuration
     */
     const confidentialClientConfig = {
        auth: {
            clientId: process.env.APP_CLIENT_ID, 
            authority: process.env.SIGN_UP_SIGN_IN_POLICY_AUTHORITY, 
            clientSecret: process.env.APP_CLIENT_SECRET,
            knownAuthorities: [process.env.AUTHORITY_DOMAIN], //This must be an array
            redirectUri: process.env.APP_REDIRECT_URI,
            validateAuthority: false
        },
        system: {
            loggerOptions: {
                loggerCallback(loglevel, message, containsPii) {
                    console.log(message);
                },
                piiLoggingEnabled: false,
                logLevel: msal.LogLevel.Verbose,
            }
        }
    };
    
    // Initialize MSAL Node
    const confidentialClientApplication = new msal.ConfidentialClientApplication(confidentialClientConfig);
    //</ms_docref_configure_msal>
    // Current web API coordinates were pre-registered in a B2C tenant.
    
    //<ms_docref_api_config>
    const apiConfig = {
        webApiScopes: [`https://${process.env.TENANT_NAME}.onmicrosoft.com/tasks-api/tasks.read`],
        anonymousUri: 'http://localhost:5000/public',
        protectedUri: 'http://localhost:5000/hello'
    };
    //</ms_docref_api_config>
    
    /**
     * The MSAL.js library allows you to pass your custom state as state parameter in the Request object
     * By default, MSAL.js passes a randomly generated unique state parameter value in the authentication requests.
     * The state parameter can also be used to encode information of the app's state before redirect. 
     * You can pass the user's state in the app, such as the page or view they were on, as input to this parameter.
     * For more information, visit: https://docs.microsoft.com/azure/active-directory/develop/msal-js-pass-custom-state-authentication-request
     */
    const APP_STATES = {
        LOGIN: 'login',
        CALL_API:'call_api'   
    }
    
    
    /** 
     * Request Configuration
     * We manipulate these two request objects below 
     * to acquire a token with the appropriate claims.
     */
     const authCodeRequest = {
        redirectUri: confidentialClientConfig.auth.redirectUri,
    };
    
    const tokenRequest = {
        redirectUri: confidentialClientConfig.auth.redirectUri,
    };
    
    
    /**
     * Using express-session middleware. Be sure to familiarize yourself with available options
     * and set them as desired. Visit: https://www.npmjs.com/package/express-session
     */
     const sessionConfig = {
        secret: process.env.SESSION_SECRET,
        resave: false,
        saveUninitialized: false,
        cookie: {
            secure: false, // set this to true on production
        }
    }
    //Create an express instance
    const app = express();
    
    //Set handlebars as your view engine
    app.engine('.hbs', engine({extname: '.hbs'}));
    app.set('view engine', '.hbs');
    app.set("views", "./views");
    
    app.use(session(sessionConfig));
    
    /**
     * This method is used to generate an auth code request
     * @param {string} authority: the authority to request the auth code from 
     * @param {array} scopes: scopes to request the auth code for 
     * @param {string} state: state of the application, tag a request
     * @param {Object} res: express middleware response object
     */
    
     const getAuthCode = (authority, scopes, state, res) => {
        // prepare the request
        console.log("Fetching Authorization code")
        authCodeRequest.authority = authority;
        authCodeRequest.scopes = scopes;
        authCodeRequest.state = state;
    
        //Each time you fetch Authorization code, update the authority in the tokenRequest configuration
        tokenRequest.authority = authority;
    
        // request an authorization code to exchange for a token
        return confidentialClientApplication.getAuthCodeUrl(authCodeRequest)
            .then((response) => {
                console.log("\nAuthCodeURL: \n" + response);
                //redirect to the auth code URL/send code to 
                res.redirect(response);
            })
            .catch((error) => {
                res.status(500).send(error);
            });
    }
    
    app.get('/', (req, res) => {
        res.render('signin', { showSignInButton: true });
    });
    
    
    
    app.get('/signin',(req, res)=>{ 
            //Initiate a Auth Code Flow >> for sign in
            //Pass the api scopes as well so that you received both the IdToken and accessToken
            getAuthCode(process.env.SIGN_UP_SIGN_IN_POLICY_AUTHORITY,apiConfig.webApiScopes, APP_STATES.LOGIN, res);
    });
    
    
    app.get('/redirect',(req, res)=>{    
        
        if (req.query.state === APP_STATES.LOGIN) {
            // prepare the request for calling the web API
            tokenRequest.authority = process.env.SIGN_UP_SIGN_IN_POLICY_AUTHORITY;
            tokenRequest.scopes = apiConfig.webApiScopes;
            tokenRequest.code = req.query.code;
            confidentialClientApplication.acquireTokenByCode(tokenRequest)
            .then((response) => {
                req.session.accessToken = response.accessToken;
                req.session.givenName = response.idTokenClaims.given_name;
                console.log('\nAccessToken:' + req.session.accessToken);
                res.render('signin', {showSignInButton: false, givenName: response.idTokenClaims.given_name});
            }).catch((error) => {
                console.log(error);
                res.status(500).send(error);
            });
        }else{
            res.status(500).send('We do not recognize this response!');
        }
    });
    
    //<ms_docref_api_express_route>
    app.get('/api', async (req, res) => {
        if(!req.session.accessToken){
            //User is not logged in and so they can only call the anonymous API
            try {
                const response = await axios.get(apiConfig.anonymousUri);
                console.log('API response' + response.data); 
                res.render('api',{data: JSON.stringify(response.data), showSignInButton: true, bg_color:'warning'});
            } catch (error) {
                console.error(error);
                res.status(500).send(error);
            }         
        }else{
            //Users have the accessToken because they signed in and the accessToken is still in the session
            console.log('\nAccessToken:' + req.session.accessToken);
            let accessToken = req.session.accessToken;
            const options = {
                headers: {
                    //accessToken used as bearer token to call a protected API
                    Authorization: `Bearer ${accessToken}`
                }
            };
    
            try {
                const response = await axios.get(apiConfig.protectedUri, options);
                console.log('API response' + response.data); 
                res.render('api',{data: JSON.stringify(response.data), showSignInButton: false, bg_color:'success', givenName: req.session.givenName});
            } catch (error) {
                console.error(error);
                res.status(500).send(error);
            }
        }     
    });
    
    //</ms_docref_api_express_route>
    
    /**
     * Sign out end point
    */
    app.get('/signout',async (req, res)=>{    
        logoutUri = process.env.LOGOUT_ENDPOINT;
        req.session.destroy(() => {
            res.redirect(logoutUri);
        });
    });
    app.listen(process.env.SERVER_PORT, () => console.log(`Msal Node Auth Code Sample app listening on port !` + process.env.SERVER_PORT));
    

    De code in het index.js-bestand bestaat uit globale variabelen en expressroutes.

    Globale variabelen:

    • confidentialClientConfig: Het MSAL-configuratieobject, dat wordt gebruikt om het vertrouwelijke clienttoepassingsobject te maken.

      /**
       * Confidential Client Application Configuration
       */
       const confidentialClientConfig = {
          auth: {
              clientId: process.env.APP_CLIENT_ID, 
              authority: process.env.SIGN_UP_SIGN_IN_POLICY_AUTHORITY, 
              clientSecret: process.env.APP_CLIENT_SECRET,
              knownAuthorities: [process.env.AUTHORITY_DOMAIN], //This must be an array
              redirectUri: process.env.APP_REDIRECT_URI,
              validateAuthority: false
          },
          system: {
              loggerOptions: {
                  loggerCallback(loglevel, message, containsPii) {
                      console.log(message);
                  },
                  piiLoggingEnabled: false,
                  logLevel: msal.LogLevel.Verbose,
              }
          }
      };
      
      // Initialize MSAL Node
      const confidentialClientApplication = new msal.ConfidentialClientApplication(confidentialClientConfig);
      
    • apiConfig: Bevat de webApiScopes-eigenschap (de waarde moet een matrix zijn) met de bereiken die zijn geconfigureerd in de web-API en worden verleend aan de web-app. Bevat ook URI's voor de web-API die moet worden aangeroepen, ofwel anonymousUri en protectedUri.

      const apiConfig = {
          webApiScopes: [`https://${process.env.TENANT_NAME}.onmicrosoft.com/tasks-api/tasks.read`],
          anonymousUri: 'http://localhost:5000/public',
          protectedUri: 'http://localhost:5000/hello'
      };
      
    • APP_STATES: Een waarde die is opgenomen in de aanvraag die ook wordt geretourneerd in de tokenreactie. Wordt gebruikt om onderscheid te maken tussen reacties die zijn ontvangen van Azure AD B2C.

    • authCodeRequest: het configuratieobject dat wordt gebruikt om autorisatiecode op te halen.

    • tokenRequest: Het configuratieobject dat wordt gebruikt om een token te verkrijgen op autorisatiecode.

    • sessionConfig: het configuratieobject voor een snelle sessie.

    • getAuthCode: Een methode waarmee de URL van de autorisatieaanvraag wordt gemaakt, zodat de gebruiker referenties invoert en toestemming geeft voor de toepassing. Hierbij wordt de getAuthCodeUrl-methode gebruikt, die is gedefinieerd in de klasse ConfidentialClientApplication.

    Express-routes:

    • /:
      • Het is de vermelding voor de web-app, die de signin pagina weergeeft.
    • /signin:
      • Meldt de gebruiker aan.
      • Roept de getAuthCode()-methode aan en geeft de authority door voor de gebruikersstroom/het beleid voor aanmelden en registreren met APP_STATES.LOGINen apiConfig.webApiScopes.
      • Hierdoor kan de eindgebruiker zich aanmelden om zijn of haar aanmeldingen in te voeren. Als de gebruiker geen account heeft, kan deze zich registreren.
      • Het laatste antwoord dat het resultaat is van dit eindpunt, bevat een autorisatiecode van B2C die is teruggezet naar het /redirect-eindpunt.
    • /redirect:
      • Het is het eindpunt dat is ingesteld als omleidings-URI voor de web-app in Azure Portal.
      • Hierbij wordt de state-queryparameter in het Azure AD B2C-antwoord gebruikt om onderscheid te maken tussen aanvragen die zijn gedaan vanuit de web-app.
      • Als de app-status APP_STATES.LOGIN is, wordt de verkregen autorisatiecode gebruikt om een token op te halen met behulp van de acquireTokenByCode()-methode. Wanneer u een token aanvraagt met behulp van acquireTokenByCode een methode, gebruikt u dezelfde bereiken die worden gebruikt tijdens het verkrijgen van de autorisatiecode. Het verkregen token bevat een accessToken, idTokenen idTokenClaims. Nadat u accessToken hebt verkregen, plaatst u deze in een sessie voor later gebruik om de web-API aan te roepen.
    • /api:
      • Roept de web-API aan.
      • Als de accessToken zich niet in de sessie bevindt, roept u het anonieme API-eindpunt (http://localhost:5000/public) aan, anders roept u het beveiligde API-eindpunt (http://localhost:5000/hello) aan.
    • /signout:
      • De gebruiker afmelden.
      • Wist de web-app-sessie en maakt een HTTP-aanroep naar het Azure AD B2c-afmeldingseindpunt.

Stap 3: De web-app en API uitvoeren

Volg de stappen in De web-app en API uitvoeren om uw web-app en web-API te testen.

Volgende stappen