تمكين المصادقة في واجهة برمجة تطبيقات ويب Node.js باستخدام Azure Active Directory B2C

في هذه المقالة، يمكنك التعرف على كيفية إنشاء تطبيق الويب الذي يستدعي واجهة برمجة تطبيقات الويب الخاصة بك. يجب حماية واجهة برمجة تطبيقات الويب بواسطة Azure Active Directory B2C (Azure AD B2C). لتخويل الوصول إلى واجهة برمجة تطبيقات الويب، يمكنك تقديم طلبات تتضمن رمز مميز صالح للوصول صادر من Azure AD B2C.

المتطلبات الأساسية

الخطوة 1: إنشاء واجهة برمجة تطبيقات ويب محمية

اتبع هذه الخطوات لإنشاء واجهة برمجة تطبيقات ويب Node.js.

الخطوة 1.1: إنشاء المشروع

استخدم Express لـ Node.js لبناء واجهة برمجة تطبيقات الويب. لإنشاء واجهة برمجة تطبيقات ويب، قم بما يلي:

  1. قم بإنشاء مجلد جديد باسم TodoList.
  2. ضمن المجلد TodoList، قم بإنشاء ملف باسم index.js.
  3. في قذيفة الأوامر، قم بتشغيلnpm init -y. ينشئ هذا الأمر ملف افتراضي package.json للمشروع Node.js.
  4. في الأمر shell، قم بتشغيل npm install express. يثبّت هذا الأمر إطار عمل Express.

الخطوة 1.2: تثبيت التبعيات

أضف مكتبة المصادقة إلى مشروع واجهة برمجة تطبيقات الويب الخاص بك. مكتبة المصادقة يوزع رأس مصادقة HTTP، التحقق من صحة الرمز المميز واستخراج المطالبات. لمزيد من المعلومات، راجع وثائق المكتبة.

لإضافة مكتبة المصادقة، قم بتثبيت الحزم عن طريق تشغيل الأمر التالي:

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

إن حزمة morgan هي برنامج وسيطة مُسجّل لطلبات HTTP لـ Node.js.

الخطوة 1.3: كتابة التعليمات البرمجية لخادم API على الويب

أضف التعليمة البرمجية التالية في ملف ⁧index.js⁩:

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

يحيط علمًا بمقتطفات التعليمات البرمجية التالية في الملف index.js:

  • استيراد مكتبة passport Azure AD

    const BearerStrategy = require('passport-azure-ad').BearerStrategy;
    
  • تعيين خيارات 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
    }
    
  • إنشاء مثيل لمكتبة passport Azure AD باستخدام خيارات Azure AD B2C

    const bearerStrategy = new BearerStrategy(options, (token, done) => {
            // Send user info using the second argument
            done(null, { }, token);
        }
    );
    
  • نقطة نهاية API المحمية. وهو يخدم الطلبات التي تتضمن رمز مميز صالح للوصول صادر من Azure AD B2C. تقوم نقطة النهاية هذه بإرجاع قيمة nameالمطالبة داخل رمز الوصول.

    // 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']});
        }
    );
    
  • نقطة نهاية API المجهولة. يمكن لتطبيق الويب أن يستدعيه دون تقديم رمز مميز للوصول. استخدمه لتصحيح أخطاء واجهة برمجة تطبيقات الويب الخاصة بك باستخدام مكالمات مجهولة.

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

الخطوة 1.4: تكوين واجهة برمجة تطبيقات الويب

أضف التكوينات إلى ملف التكوين. يحتوي الملف على معلومات حول موفر هوية Microsoft Azure Active Directory B2C الخاص بك. يستخدم تطبيق واجهة برمجة تطبيقات الويب هذه المعلومات للتحقق من رمز الوصول الذي يمرره تطبيق الويب كرمز لحاملها.

  1. ضمن مجلد جذر المشروع، أنشئ ملفconfig.json، ثم أضف إليه عنصر JSON التالي:

    {
        "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. في ملف config.json، قم بتحديث الخصائص التالية:

القسم المفتاح القيمة
credentials اسم المستأجر الجزء الأول من اسم مستأجر Microsoft Azure Active Directory B2C (على سبيل المثال، fabrikamb2c).
أوراق الاعتماد معرف العميل معرف تطبيق الويب API. لمعرفة كيفية الحصول على معرف تسجيل تطبيق الويب API، راجع المتطلبات الأساسية.
النُهُج اسم السياسة تدفقات المستخدم، أو السياسة المخصصة. لمعرفة كيفية الحصول على تدفق المستخدم أو النهج، راجع المتطلبات الأساسية.
المورد النطاق نطاقات تسجيل واجهة برمجة تطبيقات الويب الخاص بك مثل [tasks.read]. لمعرفة كيفية الحصول على نطاق واجهة برمجة تطبيقات الويب، راجع المتطلبات الأساسية.

الخطوة 2: إنشاء تطبيق ويب عقدة ويب

اتبع هذه الخطوات لإنشاء تطبيق ويب Node. يصادق تطبيق الويب المستخدم للحصول على رمز مميز للوصول يستخدم لاستدعاء واجهة برمجة تطبيقات ويب Node التي أنشأتها في الخطوة 1:

الخطوة 2.1: إنشاء مشروع العقدة

إنشاء مجلد للاحتفاظ بتطبيق العقدة، مثل call-protected-api.

  1. في المحطة الطرفية، قم بتغيير الدليل إلى مجلد تطبيق العقدة، مثل cd call-protected-api، ثم قم بتشغيل npm init -y. يقوم هذا الأمر بإنشاء package.js افتراضي على ملف لمشروع Node.js.

  2. في محطتك الطرفية، قم بـ «تشغيل npm install express». يثبّت هذا الأمر إطار عمل Express.

  3. إنشاء المزيد من المجلدات والملفات لتحقيق بنية المشروع التالية:

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

    يحتوي المجلد views على ملفات المقاود لواجهة مستخدم تطبيق الويب.

الخطوة 2.2: تثبيت التبعيات

في المحطة الطرفية، قم بتثبيت الحزم dotenv وexpress-handlebars وexpress-session و@azure/msal-node عن طريق تشغيل الأوامر التالية:

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

الخطو 2.3: إنشاء مكونات واجهة مستخدم تطبيق الويب

  1. أضف التعليمة البرمجية التالية في ملف ⁧main.hbs⁩:

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

    الملف main.hbs يوجد في المجلد layout، ويجب أن يحتوي على تعليمات HTML البرمجية المطلوبة خلال التطبيق. وهو ينفذ واجهة المستخدم التي أنشئت مع إطار عمل Bootstrap 5 CSS. يتم وضع أي واجهة مستخدم تتغير من صفحة إلى أخرى، مثل signin.hbs، في العنصر النائب المعروض كـ {{{body}}}.

  2. أضف التعليمة البرمجية التالية في ملف ⁧signin.hbs⁩:

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

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

    تعرض هذه الصفحة الاستجابة من واجهة برمجة التطبيقات. تُمكّن سمة فئة bg-{{bg_color}} في بطاقة Bootstrap واجهة المستخدم لعرض لون خلفية مختلفة لنقاط نهاية API المختلفة.

الخطوة 2.4: اكتمال التعليمات البرمجية لخادم تطبيق ويب

  1. في الملف .env، أضف التعليمات البرمجية التالية، والتي تتضمن منفذ http للخادم وتفاصيل تسجيل التطبيق وتسجيل الدخول وتسجيل تفاصيل تدفق/نهج المستخدم:

    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
    

    تعديل القيم في ملفات .env كما هو موضح في تكوين نموذج تطبيق الويب

  2. أضف التعليمة البرمجية التالية في ملف index.js لديك:

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

    تتكون التعليمات البرمجية الموجودة في ملفات index.js من متغيرات عمومية ومسارات سريعة.

    المتغيرات العمومية:

    • confidentialClientConfig: عنصر تكوين 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);
      
    • apiConfig: يحتوي على webApiScopes خاصية (يجب أن تكون قيمتها كصفيف)، وهي النطاقات التي تم تكوينها في واجهة برمجة تطبيقات الويب، ومنحها إلى تطبيق الويب. كما أن لديها URIs في واجهة برمجة التطبيقات على الويب ليتم استدعاؤها، وهي anonymousUri و 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: قيمة مضمنة في الطلب الذي تم إرجاعه أيضًا في استجابة الرمز المميز. تستخدم للتمييز بين الردود الواردة من Azure AD B2C.

    • authCodeRequest: عنصر التكوين المستخدم لاسترداد رمز التخويل.

    • tokenRequest: عنصر التكوين المستخدم للحصول على رمز مميز بواسطة التعليمة البرمجية للتخويل.

    • sessionConfig: عنصر التكوين لجلسة العمل السريعة.

    • getAuthCode: أسلوب يقوم بإنشاء عنوان URL لطلب التخويل، مما يسمح للمستخدم بإدخال بيانات الاعتماد والموافقة على التطبيق. يستخدم الأسلوب getAuthCodeUrl الذي تم تعريفه في فئة ConfidentialClientApplication.

    المسارات سريع:

    • /:
      • هو الدخول إلى تطبيق الويب، وعرض الصفحة signin.
    • /signin:
      • تسجيل دخول المستخدم.
      • يستدعي الأسلوب getAuthCode() ويقوم بتمرير authority من أجل تسجيل الدخول وتسجيل تدفق/نهج المستخدم، وAPP_STATES.LOGIN، وapiConfig.webApiScopes إليه.
      • يتسبب ذلك في تحدي المستخدم النهائي لإدخال عمليات تسجيل الدخول الخاصة به، أو إذا لم يكن لدى المستخدم حساب، يمكنه التسجيل.
      • تتضمن الاستجابة النهائية الناتجة عن نقطة النهاية هذه التعليمة البرمجية للتخويل من B2C تم نشره مرة أخرى إلى نقطة نهاية /redirect.
    • /redirect:
      • تمثل نقطة النهاية التي تم تعيينها كـ إعادة توجيه لمعرّف الموارد المنتظم لتطبيق الويب في مدخل Azure.
      • ويستخدم معلمة الاستعلام state في الطلب من Azure AD B2C للتمييز بين الطلبات التي تم إجراؤها من تطبيق الويب.
      • إذا كانت حالة التطبيق هي APP_STATES.LOGIN، يتم استخدام التعليمة البرمجية للتخويل المكتسب لاسترداد رمز مميز من خلال استخدام الأسلوب acquireTokenByCode(). عند طلب رمز مميز باستخدام الأسلوب acquireTokenByCode، يمكنك استخدام نفس النطاقات المستخدمة أثناء الحصول على التعليمة البرمجية للتخويل. يتضمن الرمز المميز المكتسب accessToken وidToken وidTokenClaims. بعد الحصول على accessToken، يمكنك وضعه في جلسة عمل لاستخدامها لاحقًا في استدعاء واجهة برمجة تطبيقات الويب.
    • /api:
      • استدعاء واجهة برمجة تطبيقات الويب.
      • إذا لم يكن accessToken في جلسة العمل، اتصل بنقطة نهاية API المجهولة (http://localhost:5000/public)، وخلاف ذلك، اتصل بنقطة نهاية API المحمية (http://localhost:5000/hello).
    • /signout:
      • تسجيل خروج المستخدم.
      • يمسح تطبيق الويب الجلسة ويستدعي HTTP إلى نقطة نهاية تسجيل خروج Microsoft Azure AD B2c.

الخطوة 3: تشغيل تطبيق الويب و API

اتبع الخطوات في تشغيل تطبيق الويب و API لاختبار تطبيق الويب وواجهة برمجة تطبيقات الويب.

الخطوات التالية