Bagikan melalui


Mengaktifkan autentikasi di API web Node.js Anda sendiri dengan menggunakan Azure Active Directory B2C

Penting

Berlaku mulai 1 Mei 2025, Azure AD B2C tidak akan lagi tersedia untuk dibeli untuk pelanggan baru. Pelajari lebih lanjut di FAQ kami.

Dalam artikel ini, Anda mempelajari cara membuat aplikasi web yang memanggil API web Anda. API web perlu dilindungi oleh Azure Active Directory B2C (Azure AD B2C). Untuk mengotorisasi akses ke API web, Anda melayani permintaan yang menyertakan token akses valid yang dikeluarkan oleh Azure AD B2C.

Prasyarat

Langkah 1: Membuat API web yang dilindungi

Ikuti langkah-langkah ini untuk membuat API web Node.js Anda.

Langkah 1.1: Membuat proyek

Gunakan Express untuk Node.js untuk membangun API web. Untuk membuat API web, lakukan hal berikut:

  1. Buat folder baru bernama TodoList.
  2. Di bawah TodoList folder, buat file bernama index.js.
  3. Pada jendela perintah, jalankan npm init -y. Perintah ini membuat file package.json default untuk proyek Node.js Anda.
  4. Dalam command shell, jalankan npm install express. Perintah ini menginstal kerangka kerja Ekspres.

Langkah 1.2: Menginstal dependensi

Tambahkan pustaka autentikasi ke proyek API web Anda. Pustaka autentikasi mengurai header autentikasi HTTP, memvalidasi token, dan mengekstrak klaim. Untuk informasi selengkapnya, tinjau dokumentasi untuk pustaka.

Untuk menambahkan pustaka autentikasi, instal paket dengan menjalankan perintah berikut:

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

Paket morgan adalah middleware pencatat permintaan HTTP untuk Node.js.

Langkah 1.3: Tulis kode server API web

index.js Dalam file, tambahkan kode berikut:

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

Perhatikan cuplikan kode berikut dalam index.jsfile:

  • Mengimpor pustaka paspor Microsoft Entra

    const BearerStrategy = require('passport-azure-ad').BearerStrategy;
    
  • Mengatur pilihan 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
    }
    
  • Menginisialisasi pustaka paspor Microsoft Entra dengan opsi Azure AD B2C.

    const bearerStrategy = new BearerStrategy(options, (token, done) => {
            // Send user info using the second argument
            done(null, { }, token);
        }
    );
    
  • Titik akhir API yang dilindungi. Ini melayani permintaan yang menyertakan token akses yang dikeluarkan Azure AD B2C yang valid. Titik akhir ini mengembalikan nilai name klaim dalam token akses.

    // 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']});
        }
    );
    
  • Titik akhir API anonim. Aplikasi web dapat memanggilnya tanpa menyajikan token akses. Gunakan untuk men-debug API web Anda dengan panggilan anonim.

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

Langkah 1.4: Mengonfigurasi API web

Tambahkan konfigurasi ke file konfigurasi. File berisi informasi tentang penyedia identitas Azure AD B2C Anda. Aplikasi API web menggunakan informasi ini untuk memvalidasi token akses yang diteruskan aplikasi web sebagai token pembawa.

  1. Di bawah folder akar proyek, buat config.json file, lalu tambahkan ke dalamnya objek JSON berikut:

    {
        "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. Dalam file config.json, perbarui properti berikut:

Bagian Kunci Nilai
Bukti identitas namaPenyewa Bagian pertama dari nama penyewa Azure AD B2C Anda (misalnya, fabrikamb2c).
Bukti identitas ID klien ID aplikasi API web. Untuk mempelajari cara mendapatkan ID pendaftaran aplikasi API web Anda, lihat Prasyarat.
Kebijakan Nama Kebijakan Alur pengguna, atau kebijakan kustom. Untuk mempelajari cara mendapatkan alur atau kebijakan pengguna Anda, lihat Prasyarat.
Sumber daya ruang lingkup Cakupan pendaftaran aplikasi API web Anda seperti [tasks.read]. Untuk mempelajari cara mendapatkan cakupan API web Anda, lihat Prasyarat.

Langkah 2: Membuat aplikasi web Node.js

Ikuti langkah-langkah ini untuk membuat aplikasi web Node. Aplikasi web ini mengautentikasi pengguna untuk memperoleh token akses yang digunakan untuk memanggil API web Node yang Anda buat di langkah 1:

Langkah 2.1: Membuat proyek simpul

Buat folder untuk menyimpan aplikasi node Anda, seperti call-protected-api.

  1. Di terminal Anda, ubah direktori ke folder aplikasi simpul Anda, seperti cd call-protected-api, dan jalankan npm init -y. Perintah ini membuat file package.json default untuk proyek Node.js Anda.

  2. Di terminal Anda, jalankan npm install express. Perintah ini menginstal kerangka kerja Ekspres.

  3. Buat lebih banyak folder dan file untuk mencapai struktur proyek berikut:

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

    Folder views berisi file handlebar untuk UI aplikasi web.

Langkah 2.2: Instal dependensi

Di terminal Anda, instal paket dotenv, express-handlebars, express-session, dan @azure/msal-node dengan menjalankan perintah berikut:

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

Langkah 2.3: Membangun komponen UI aplikasi web

  1. main.hbs Dalam file, tambahkan kode berikut:

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

    File main.hbs berada di layout folder dan harus berisi kode HTML apa pun yang diperlukan di seluruh aplikasi Anda. Ini mengimplementasikan UI yang dibangun dengan Bootstrap 5 CSS Framework. UI apa pun yang berubah dari satu halaman ke halaman lainnya, seperti signin.hbs, ditempatkan dalam placeholder yang ditampilkan sebagai {{{body}}}.

  2. signin.hbs Dalam file, tambahkan kode berikut:

    <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 Dalam file, tambahkan kode berikut:

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

    Halaman ini menampilkan respons dari API. Atribut bg-{{bg_color}} kelas dalam kartu Bootstrap memungkinkan UI menampilkan warna latar belakang yang berbeda untuk titik akhir API yang berbeda.

Langkah 2.4: Menyelesaikan kode server aplikasi web

  1. .env Dalam file, tambahkan kode berikut, yang mencakup port http server, detail pendaftaran aplikasi, dan rincian masuk dan mendaftarkan alur/kebijakan pengguna:

    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
    

    Ubah nilai dalam .env file seperti yang dijelaskan di Mengonfigurasi contoh aplikasi web

  2. Di file Anda index.js , tambahkan kode berikut:

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

    Kode dalam index.js file terdiri dari variabel global dan rute ekspres.

    Variabel global:

    • confidentialClientConfig: Objek konfigurasi MSAL, yang digunakan untuk membuat objek aplikasi klien rahasia.

      /**
       * 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: Berisi properti webApiScopes (nilainya harus berupa array), yaitu cakupan yang telah dikonfigurasi di API web dan diberikan hak aksesnya ke aplikasi web. Ini juga memiliki URI ke API web yang akan dipanggil, yaitu anonymousUri dan 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: Nilai yang disertakan dalam permintaan yang juga dikembalikan dalam respons token. Digunakan untuk membedakan antara respons yang diterima dari Azure AD B2C.

    • authCodeRequest: Objek konfigurasi yang digunakan untuk mengambil kode otorisasi.

    • tokenRequest: Objek konfigurasi yang digunakan untuk memperoleh token dengan kode otorisasi.

    • sessionConfig: Objek konfigurasi untuk sesi ekspres.

    • getAuthCode: Metode yang membuat URL permintaan otorisasi, memungkinkan pengguna memasukkan kredensial dan persetujuan ke aplikasi. Ini menggunakan getAuthCodeUrl metode , yang didefinisikan dalam kelas ConfidentialClientApplication .

    Rute ekspres:

    • /:
      • Ini adalah entri ke aplikasi web, dan merender halaman signin.
    • /signin:
      • Masuk ke akun pengguna.
      • getAuthCode() Memanggil metode dan meneruskan authority untuk Masuk dan Daftar alur/kebijakan pengguna, APP_STATES.LOGIN, dan apiConfig.webApiScopes kepadanya.
      • Ini menyebabkan pengguna akhir ditantang untuk memasukkan login mereka, atau jika pengguna tidak memiliki akun, mereka dapat mendaftar.
      • Respons akhir yang dihasilkan oleh titik akhir ini menyertakan kode otorisasi dari B2C yang diposting kembali ke titik akhir /redirect.
    • /redirect:
      • Ini adalah titik akhir yang ditetapkan sebagai URI Pengalihan untuk aplikasi web di portal Microsoft Azure.
      • Ini menggunakan state parameter kueri dalam respons Azure AD B2C, untuk membedakan antara permintaan yang dibuat dari aplikasi web.
      • Jika status aplikasi adalah APP_STATES.LOGIN, kode otorisasi yang diperoleh digunakan untuk mengambil token menggunakan acquireTokenByCode() metode . Saat meminta token menggunakan acquireTokenByCode metode, Anda menggunakan cakupan yang sama yang digunakan saat memperoleh kode otorisasi. Token yang diperoleh mencakup accessToken, idToken, dan idTokenClaims. Setelah Anda memperoleh accessToken, Anda memasukkannya ke dalam sesi untuk digunakan nanti untuk memanggil API web.
    • /api:
      • Memanggil API web.
      • accessToken Jika tidak ada dalam sesi, panggil titik akhir API anonim (http://localhost:5000/public), jika tidak, panggil titik akhir API yang dilindungi (http://localhost:5000/hello).
    • /signout:
      • Mengeluarkan pengguna.
      • menghapus sesi aplikasi web dan melakukan panggilan http ke titik akhir keluar Azure AD B2C.

Langkah 3: Jalankan aplikasi web dan API

Ikuti langkah-langkah dalam Menjalankan aplikasi web dan API untuk menguji aplikasi web dan API web Anda.

Langkah selanjutnya