Sdílet prostřednictvím


Povolení ověřování ve vlastním webovém rozhraní API Node.js pomocí Azure Active Directory 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.

V tomto článku se dozvíte, jak vytvořit webovou aplikaci, která volá vaše webové rozhraní API. Webové rozhraní API musí být chráněné službou Azure Active Directory B2C (Azure AD B2C). Pokud chcete autorizovat přístup k webovému rozhraní API, obsluhujete požadavky, které obsahují platný přístupový token vydaný službou Azure AD B2C.

Požadavky

Krok 1: Vytvoření chráněného webového rozhraní API

Podle těchto kroků vytvořte webové rozhraní API pro Node.js.

Krok 1.1: Vytvoření projektu

K vytvoření webového rozhraní API použijte Express pro Node.js . Pokud chcete vytvořit webové rozhraní API, postupujte takto:

  1. Vytvořte novou složku s názvem TodoList.
  2. TodoList Ve složce vytvořte soubor s názvem index.js.
  3. V příkazovém prostředí spusťte npm init -y. Tento příkaz vytvoří výchozí soubor package.json pro váš projekt Node.js.
  4. V příkazovém prostředí spusťte npm install express. Tento příkaz nainstaluje architekturu Express.

Krok 1.2: Instalace závislostí

Přidejte knihovnu ověřování do projektu webového rozhraní API. Knihovna ověřování analyzuje hlavičku ověřování HTTP, ověří token a extrahuje deklarace identity. Další informace najdete v dokumentaci ke knihovně.

Pokud chcete přidat knihovnu ověřování, nainstalujte balíčky spuštěním následujícího příkazu:

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

Balíček morgan je middleware pro protokolování HTTP požadavků pro Node.js.

Krok 1.3: Napsání kódu serveru webového rozhraní API

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

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

Poznamenejte si následující fragmenty kódu v index.jssouboru:

  • Importuje knihovnu Microsoft Entra passport

    const BearerStrategy = require('passport-azure-ad').BearerStrategy;
    
  • Nastaví možnosti Azure AD B2C.

    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
    }
    
  • Vytvoření instance knihovny Microsoft Entra passport pomocí možností Azure AD B2C

    const bearerStrategy = new BearerStrategy(options, (token, done) => {
            // Send user info using the second argument
            done(null, { }, token);
        }
    );
    
  • Koncový bod chráněného rozhraní API. Slouží k žádostem, které zahrnují platný přístupový token vydaný službou Azure AD B2C. Tento koncový bod vrátí hodnotu name nároku uvnitř přístupového tokenu.

    // 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']});
        }
    );
    
  • Anonymní koncový bod rozhraní API. Webová aplikace ji může volat bez prezentování přístupového tokenu. Slouží k ladění webového rozhraní API pomocí anonymních volání.

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

Krok 1.4: Konfigurace webového rozhraní API

Přidejte konfigurace do konfiguračního souboru. Soubor obsahuje informace o vašem zprostředkovateli identity Azure AD B2C. Aplikace webového rozhraní API tyto informace používá k ověření přístupového tokenu, který webová aplikace předává jako nosný token.

  1. V kořenové složce projektu vytvořte config.json soubor a pak do ní přidejte následující objekt JSON:

    {
        "credentials": {
            "tenantName": "fabrikamb2c",
            "clientID": "Enter_the_Application_Id_Here"
        },
        "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. config.json V souboru aktualizujte následující vlastnosti:

Oddíl Klíč Hodnota
pověření názevNájemce První část názvu klienta Azure AD B2C (například fabrikamb2c).
pověření Klientský ID ID webové API aplikace. Informace o tom, jak získat ID registrace aplikace webového rozhraní API, najdete v tématu Požadavky.
politiky název politiky Toky uživatelů nebo vlastní pravidla. Jak získat tok uživatele nebo zásady, naleznete v sekci Požadavky.
zdroj rozsah působnosti Rozsahy registrace vaší aplikace webového rozhraní API, například [tasks.read]. Informace o tom, jak získat obor webového rozhraní API, najdete v tématu Požadavky.

Krok 2: Vytvoření webové aplikace Node

Pomocí těchto kroků vytvořte webovou aplikaci Node. Tato webová aplikace ověřuje uživatele, aby získal přístupový token, který se používá k volání webového rozhraní API Node, které jste vytvořili v kroku 1:

Krok 2.1: Vytvoření projektu uzlu

Vytvořte složku pro uložení aplikace uzlu, například call-protected-api.

  1. V terminálu změňte adresář do složky aplikace node, například cd call-protected-apia spusťte npm init -y. Tento příkaz vytvoří výchozí soubor package.json pro váš projekt Node.js.

  2. V terminálu spusťte npm install express. Tento příkaz nainstaluje architekturu Express.

  3. Vytvořte další složky a soubory, abyste dosáhli následující struktury projektu:

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

    Složka views obsahuje soubory úchytů pro uživatelské rozhraní webové aplikace.

Krok 2.2: Instalace závislostí

V terminálu nainstalujte balíčky dotenv, express-handlebars, express-session a @azure/msal-node spuštěním následujících příkazů:

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

Krok 2.3: Sestavení komponent uživatelského rozhraní webové aplikace

  1. main.hbs Do souboru přidejte následující kód:

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

    Soubor main.hbs je ve layout složce a měl by obsahovat libovolný kód HTML, který se vyžaduje v celé aplikaci. Implementuje uživatelské rozhraní vytvořené pomocí architektury CSS Bootstrap 5. Jakékoli uživatelské rozhraní, které se změní ze stránky na stránku, například signin.hbs, se umístí do zástupného symbolu zobrazeného jako {{{body}}}.

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

    <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. api.hbs Do souboru přidejte následující kód:

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

    Na této stránce se zobrazí odpověď z rozhraní API. Atribut bg-{{bg_color}} třídy na kartě Bootstrap umožňuje uživatelskému rozhraní zobrazit jinou barvu pozadí pro různé koncové body rozhraní API.

Krok 2.4: Dokončení kódu serveru webových aplikací

  1. .env Do souboru přidejte následující kód, který zahrnuje port HTTP serveru, podrobnosti o registraci aplikace a přihlášení a registraci toku uživatele nebo podrobnosti o zásadách:

    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
    

    Upravte hodnoty v souborech.env, jak je vysvětleno v části Konfigurace ukázkové webové aplikace.

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

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

    Kód v index.js souboru se skládá z globálních proměnných a expresních tras.

    Globální proměnné:

    • confidentialClientConfig: Objekt konfigurace MSAL, který slouží k vytvoření důvěrného objektu klientské aplikace.

      /**
       * 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: Obsahuje webApiScopes vlastnost (hodnota musí být pole), což jsou obory nakonfigurované ve webovém rozhraní API a udělené webové aplikaci. Obsahuje také identifikátory URI webového rozhraní API, které se mají volat, tj anonymousUriprotectedUri.

      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: Hodnota zahrnutá v požadavku, který se vrátí také v odpovědi tokenu. Používá se k rozlišení odpovědí přijatých z Azure AD B2C.

    • authCodeRequest: Objekt konfigurace použitý k načtení autorizačního kódu.

    • tokenRequest: Objekt konfigurace použitý k získání tokenu autorizačním kódem.

    • sessionConfig: Objekt konfigurace pro expresní relaci.

    • getAuthCode: Metoda, která vytvoří adresu URL žádosti o autorizaci, která umožní zadání přihlašovacích údajů uživatele a souhlas s aplikací. Používá metodu getAuthCodeUrl , která je definována ve třídě ConfidentialClientApplication .

    Expresní trasy:

    • /:
      • Je to položka webové aplikace a vykreslí signin stránku.
    • /signin:
      • Přihlásí se k uživateli.
      • Volá getAuthCode() metodu a předává metodu authoritypřihlášení a registraci toku/zásad APP_STATES.LOGINuživatele a apiConfig.webApiScopes do ní.
      • To způsobí, že koncový uživatel bude vyzván k zadání přihlašovacích údajů nebo pokud uživatel nemá účet, může se zaregistrovat.
      • Konečná odpověď vyplývající z tohoto koncového bodu zahrnuje autorizační kód z B2C vystavený zpět do koncového /redirect bodu.
    • /redirect:
      • Je to koncový bod nastavený jako identifikátor URI přesměrování pro webovou aplikaci na webu Azure Portal.
      • Používá state parametr dotazu v odpovědi Azure AD B2C k rozlišení požadavků provedených z webové aplikace.
      • Pokud je APP_STATES.LOGINstav aplikace , autorizační kód získaný se použije k načtení tokenu acquireTokenByCode() pomocí metody. Při vyžádání tokenu pomocí acquireTokenByCode metody použijete stejné obory, které jste použili při získávání autorizačního kódu. Získaný token obsahuje symbol accessToken, idTokena idTokenClaims. Jakmile ho accessTokenzískáte, vložíte ho do relace pro pozdější použití k volání webového rozhraní API.
    • /api:
      • Volá webové rozhraní API.
      • accessToken Pokud není v relaci, zavolejte anonymní koncový bod rozhraní API (http://localhost:5000/public), jinak zavolejte chráněný koncový bod rozhraní API (http://localhost:5000/hello).
    • /signout:
      • Odhlásí uživatele.
      • vymaže relaci webové aplikace a provede volání HTTP do koncového bodu odhlášení Azure AD B2C.

Krok 3: Spuštění webové aplikace a rozhraní API

Postupujte podle kroků v části Spuštění webové aplikace a rozhraní API a otestujte webovou aplikaci a webové rozhraní API.

Další kroky