تمكين المصادقة في تطبيق الويب Node الخاص بك باستخدام Microsoft Azure Active Directory B2C
في هذه المقالة، ستتعرف على كيفية إضافة مصادقة Microsoft Azure Active Directory B2C (Microsoft Azure AD B2C) في تطبيق الويب Node.js الخاص بك. ستقوم بتمكين المستخدمين من تسجيل الدخول وتسجيل الخروج وتحديث ملفات التعريف وإعادة تعيين كلمات المرور باستخدام تدفقات مستخدم Microsoft Azure AD B2C. تستخدم هذه المقالة Microsoft Authentication Library (MSAL) لـ Node لتبسيط إضافة مصادقة إلى تطبيق الويب Node.
الهدف من هذه المقالة هو استبدال نموذج التطبيق الذي استخدمته في تكوين المصادقة في نموذج تطبيق ويب Node.js باستخدام Microsoft Azure AD B2C في تطبيق الويب Node.js الخاص بك.
تستخدم هذه المقالة Node.js وExpress لإنشاء تطبيق ويب Node.js أساسي. تستخدم طرق عرض التطبيق Handlebars.
المتطلبات الأساسية
- أكمل الخطوات في تكوين المصادقة في نموذج تطبيق ويب Node.js باستخدام Microsoft Azure AD B2C. ستقوم بإنشاء تدفقات مستخدم Microsoft Azure AD B2C وتسجيل تطبيق ويب في مدخل Microsoft Azure.
الخطوة 1: إنشاء مشروع node
قم بإنشاء مجلد لاستضافة تطبيق العقدة الخاص بك، مثل active-directory-b2c-msal-node-sign-in-sign-out-webapp
.
في المحطة الطرفية، قم بتغيير الدليل إلى مجلد تطبيق العقدة، مثل
cd active-directory-b2c-msal-node-sign-in-sign-out-webapp
، ثم قم بالتشغيلnpm init -y
. ينشئ هذا الأمر ملف افتراضيpackage.json
للمشروع Node.js.في محطتك الطرفية، قم بـ «تشغيل
npm install express
». يثبّت هذا الأمر إطار عمل Express.إنشاء المزيد من المجلدات والملفات لتحقيق بنية المشروع التالية:
active-directory-b2c-msal-node-sign-in-sign-out-webapp/ ├── index.js └── package.json └── .env └── views/ └── layouts/ └── main.hbs └── signin.hbs
يحتوي views
المجلد على ملفات المقود لواجهة مستخدم تطبيق الويب.
الخطوة 2: تثبيت تبعيات التطبيق
في المحطة الطرفية، قم بتثبيت الحزم dotenv
وexpress-handlebars
وexpress-session
و@azure/msal-node
عن طريق تشغيل الأوامر التالية:
npm install dotenv
npm install express-handlebars
npm install express-session
npm install @azure/msal-node
الخطوة 3: إنشاء مكونات واجهة المستخدم للتطبيق
أضف التعليمة البرمجية التالية في ملف 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>Tutorial | Authenticate users with 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-secondary" href="/signin" aria-haspopup="true" aria-expanded="false">
Sign in
</a>
</div>
{{else}}
<div class="ml-auto">
<a type="button" id="EditProfile" class="btn btn-warning" href="/profile" aria-haspopup="true" aria-expanded="false">
Edit profile
</a>
<a type="button" id="PasswordReset" class="btn btn-warning" href="/password" aria-haspopup="true" aria-expanded="false">
Reset password
</a>
</div>
<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 مطلوب في جميع أنحاء التطبيق الخاص بك. يتم وضع أي واجهة مستخدم تتغير من طريقة عرض إلى أخرى، كما هو الحال في signin.hbs
، في العنصر النائب الذي يظهر كـ {{{body}}}
.
main.hbs
الملف بتنفيذ واجهة المستخدم بنيت مع إطار Bootstrap 5 CSS. سترى مكونات (أزرار) واجهة المستخدم Edit password، وReset password، وSign out عند تسجيل الدخول. سترى Sign in عند تسجيل الخروج. ويتم التحكم في هذا السلوك بواسطة المتغير المنطقي showSignInButton
، الذي يرسله خادم التطبيق.
أضف التعليمة البرمجية التالية في ملف signin.hbs
:
<div class="col-md-3" style="margin:auto">
<div class="card text-center">
<div class="card-body">
{{#if showSignInButton}}
<h5 class="card-title">Please sign-in to acquire an ID token</h5>
{{else}}
<h5 class="card-title">You have signed in</h5>
{{/if}}
</div>
<div class="card-body">
{{#if message}}
<h5 class="card-title text-danger">{{message}}</h5>
{{/if}}
</div>
</div>
</div>
الخطوة 4: تكوين خادم ويب وعميل MSAL
في الملف
.env
، أضِف التعليمة البرمجية التالية وحدثها كما هو موضح في تكوين نموذج تطبيق الويب.#HTTP port 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> #B2C sign up and sign in user flow/policy 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> #B2C password reset user flow/policy authority RESET_PASSWORD_POLICY_AUTHORITY=https://<your-tenant-name>.b2clogin.com/<your-tenant-name>.onmicrosoft.com/<reset-password-user-flow-name> #B2C edit profile user flow/policy authority EDIT_PROFILE_POLICY_AUTHORITY=https://<your-tenant-name>.b2clogin.com/<your-tenant-name>.onmicrosoft.com/<profile-edit-user-flow-name> #B2C authority domain AUTHORITY_DOMAIN=https://<your-tenant-name>.b2clogin.com #client redirect url APP_REDIRECT_URI=http://localhost:3000/redirect #Logout endpoint 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
في
index.js
الملف، أضف التعليمات البرمجية التالية لاستخدام تبعيات التطبيق:require('dotenv').config(); const express = require('express'); const session = require('express-session'); const {engine} = require('express-handlebars'); const msal = require('@azure/msal-node');
في ملف
index.js
الخاص بك، أضِف التعليمة البرمجية التالية لتكوين مكتبة المصادقة:/** * 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);
confidentialClientConfig
هو عنصر تكوين MSAL المستخدم للاتصال بنقاط نهاية مصادقة مستأجر Microsoft Azure AD B2C.لإضافة المزيد من المتغيرات العمومية في ملف
index.js
، أضِف التعليمات البرمجية التالية:/** * 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 * In this scenario, the states also serve to show the action that was requested of B2C since only one redirect URL is possible. */ const APP_STATES = { LOGIN: 'login', LOGOUT: 'logout', PASSWORD_RESET: 'password_reset', EDIT_PROFILE : 'update_profile' } /** * 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 } }
APP_STATES
: تستخدم للتمييز بين الردود الواردة من Azure AD B2C عن طريق وضع علامات على الطلبات. هناك URI واحد فقط لإعادة التوجيه لأي عدد من الطلبات المرسلة إلى Microsoft Azure AD B2C.authCodeRequest
: كائن التكوين المستخدم لاسترداد رمز التخويل.tokenRequest
: كائن التكوين المستخدم للحصول على رمز مميز بواسطة رمز التخويل.sessionConfig
: كائن التكوين لجلسة عمل Express.
لتعيين مشغل قالب العرض وتكوين جلسة عمل Express، أضف التعليمات البرمجية التالية في
index.js
الملف://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"); //usse session configuration app.use(session(sessionConfig));
الخطوة 5: إضافة مسارات Express
قبل إضافة مسار التطبيق، أضِف المنطق الذي يسترد عنوان URL لرمز التخويل، وهو المرحلة الأولى من تدفق منح رمز التخويل. أضف التعليمة البرمجية التالية في ملف index.js
:
/**
* 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
* @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 relevant 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);
});
}
authCodeRequest
الكائن يحتوي على خصائص redirectUri
و authority
و scopes
و state
. يتم تمرير الكائن إلى getAuthCodeUrl
الأسلوب كمعلمة.
أضف التعليمة البرمجية التالية في ملف index.js
:
app.get('/', (req, res) => {
res.render('signin', { showSignInButton: true });
});
app.get('/signin',(req, res)=>{
//Initiate a Auth Code Flow >> for sign in
//no scopes passed. openid, profile and offline_access will be used by default.
getAuthCode(process.env.SIGN_UP_SIGN_IN_POLICY_AUTHORITY, [], APP_STATES.LOGIN, res);
});
/**
* Change password end point
*/
app.get('/password',(req, res)=>{
getAuthCode(process.env.RESET_PASSWORD_POLICY_AUTHORITY, [], APP_STATES.PASSWORD_RESET, res);
});
/**
* Edit profile end point
*/
app.get('/profile',(req, res)=>{
getAuthCode(process.env.EDIT_PROFILE_POLICY_AUTHORITY, [], APP_STATES.EDIT_PROFILE, res);
});
/**
* Sign out end point
*/
app.get('/signout',async (req, res)=>{
logoutUri = process.env.LOGOUT_ENDPOINT;
req.session.destroy(() => {
//When session destruction succeeds, notify B2C service using the logout uri.
res.redirect(logoutUri);
});
});
app.get('/redirect',(req, res)=>{
//determine the reason why the request was sent by checking the state
if (req.query.state === APP_STATES.LOGIN) {
//prepare the request for authentication
tokenRequest.code = req.query.code;
confidentialClientApplication.acquireTokenByCode(tokenRequest).then((response)=>{
req.session.sessionParams = {user: response.account, idToken: response.idToken};
console.log("\nAuthToken: \n" + JSON.stringify(response));
res.render('signin',{showSignInButton: false, givenName: response.account.idTokenClaims.given_name});
}).catch((error)=>{
console.log("\nErrorAtLogin: \n" + error);
});
}else if (req.query.state === APP_STATES.PASSWORD_RESET) {
//If the query string has a error param
if (req.query.error) {
//and if the error_description contains AADB2C90091 error code
//Means user selected the Cancel button on the password reset experience
if (JSON.stringify(req.query.error_description).includes('AADB2C90091')) {
//Send the user home with some message
//But always check if your session still exists
res.render('signin', {showSignInButton: false, givenName: req.session.sessionParams.user.idTokenClaims.given_name, message: 'User has cancelled the operation'});
}
}else{
res.render('signin', {showSignInButton: false, givenName: req.session.sessionParams.user.idTokenClaims.given_name});
}
}else if (req.query.state === APP_STATES.EDIT_PROFILE){
tokenRequest.scopes = [];
tokenRequest.code = req.query.code;
//Request token with claims, including the name that was updated.
confidentialClientApplication.acquireTokenByCode(tokenRequest).then((response)=>{
req.session.sessionParams = {user: response.account, idToken: response.idToken};
console.log("\AuthToken: \n" + JSON.stringify(response));
res.render('signin',{showSignInButton: false, givenName: response.account.idTokenClaims.given_name});
}).catch((error)=>{
//Handle error
});
}else{
res.status(500).send('We do not recognize this response!');
}
});
مسارات Express هي:
/
:- يستخدم لإدخال تطبيق الويب.
- فإنه يجعل
signin
الصفحة.
/signin
:- يُستخدم عند تسجيل الدخول.
- يستدعي
getAuthCode()
الأسلوب ويمرauthority
لـتسجيل الدخول والاشتراك تدفق المستخدم/النهج،APP_STATES.LOGIN
و صفيف فارغscopes
إليه. - إذا لزم الأمر، فإنه يسبب تحدياً لإدخال بيانات الاعتماد الخاصة بك. إذا لم يكن لديك حساب، فسيطالبك بالتسجيل.
- تتضمن الاستجابة النهائية التي تنتج عن هذا المسار رمز تخويل من Microsoft Azure AD B2C تم نشره مرة أخرى إلى المسار
/redirect
.
/password
:- يُستخدم عند إعادة تعيين كلمة مرور.
- فإنه يستدعي
getAuthCode()
الطريقة ويمررauthority
لسياسة أو تدفق المستخدم لإعادة تعيين كلمة المرور،APP_STATES.PASSWORD_RESET
ومجموعة فارغةscopes
لها. - يمكّنك من تغيير كلمة المرور الخاصة بك باستخدام تجربة إعادة تعيين كلمة المرور، أو يمكنهم إلغاء العملية.
- تتضمن الاستجابة النهائية التي تنتج عن هذا المسار رمز تخويل من Microsoft Azure AD B2C تم نشره مرة أخرى إلى المسار
/redirect
. إذا قمت بإلغاء العملية، يُعاد نشر الخطأ.
/profile
:- يُستخدم عند تحديث ملف التعريف الخاص بك.
- فإنه يستدعي
getAuthCode()
الطريقة ويمررauthority
لسياسة أو تدفق المستخدم لتحرير الملف الشخصي،APP_STATES.EDIT_PROFILE
ومجموعة فارغةscopes
لها. - يمكّنك من تحديث ملف التعريف الخاص بك، واستخدام تجربة تحرير ملف التعريف.
- تتضمن الاستجابة النهائية التي تنتج عن هذا المسار رمز تخويل من Microsoft Azure AD B2C تم نشره مرة أخرى إلى المسار
/redirect
.
/signout
:- يُستخدم عند تسجيل الخروج.
- يمسح تطبيق الويب الجلسة، ويستدعي HTTP إلى نقطة نهاية تسجيل الخروج Microsoft Azure AD B2C.
/redirect
:- يمثل المسار الذي تم تعيينه كـ Redirect URI لتطبيق الويب في مدخل Microsoft Azure.
- يستخدم معلمة الاستعلام
state
في الطلب من Microsoft Azure AD B2C للتمييز بين الطلبات التي يتم إجراؤها من تطبيق الويب. يعالج جميع عمليات إعادة التوجيه من Microsoft Azure AD B2C، باستثناء تسجيل الخروج. - إذا كانت حالة التطبيق
APP_STATES.LOGIN
، يتم استخدام رمز التخويل المكتسب لاسترداد رمز مميز من خلالacquireTokenByCode()
الأسلوب. يتضمن هذا الرمز المميزidToken
و، والذي يتمidTokenClaims
استخدامه لتعريف المستخدم. - إذا كانت حالة التطبيق
APP_STATES.PASSWORD_RESET
،فإنه يعالج أي خطأ، مثلuser cancelled the operation
. يحدد رمز الخطأAADB2C90091
هذا الخطأ. وإلا، فإنه يقرر تجربة المستخدم التالي. - إذا كانت حالة التطبيق
APP_STATES.EDIT_PROFILE
، فإنه يستخدم رمز التخويل للحصول على رمز مميز. يحتوي الرمز المميز علىidTokenClaims
، والذي يتضمن التغييرات الجديدة.
الخطوة 6: بدء تشغيل خادم Node
لبدء تشغيل خادم العقدة، أضف التعليمات البرمجية التالية في index.js
الملف:
app.listen(process.env.SERVER_PORT, () => {
console.log(`Msal Node Auth Code Sample app listening on port !` + process.env.SERVER_PORT);
});
بعد إجراء جميع التغييرات المطلوبة في الملف index.js
، يجب أن يبدو مشابهاً للملف التالي:
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
//<ms_docref_use_app_dependencies>
require('dotenv').config();
const express = require('express');
const session = require('express-session');
const {engine} = require('express-handlebars');
const msal = require('@azure/msal-node');
//</ms_docref_use_app_dependencies>
//<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>
//<ms_docref_global_variable>
/**
* 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
* In this scenario, the states also serve to show the action that was requested of B2C since only one redirect URL is possible.
*/
const APP_STATES = {
LOGIN: 'login',
LOGOUT: 'logout',
PASSWORD_RESET: 'password_reset',
EDIT_PROFILE : 'update_profile'
}
/**
* 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
}
}
//</ms_docref_global_variable>
//<ms_docref_view_tepmplate_engine>
//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");
//usse session configuration
app.use(session(sessionConfig));
//</ms_docref_view_tepmplate_engine>
//<ms_docref_authorization_code_url>
/**
* 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
* @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 relevant 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);
});
}
//</ms_docref_authorization_code_url>
//<ms_docref_app_endpoints>
app.get('/', (req, res) => {
res.render('signin', { showSignInButton: true });
});
app.get('/signin',(req, res)=>{
//Initiate a Auth Code Flow >> for sign in
//no scopes passed. openid, profile and offline_access will be used by default.
getAuthCode(process.env.SIGN_UP_SIGN_IN_POLICY_AUTHORITY, [], APP_STATES.LOGIN, res);
});
/**
* Change password end point
*/
app.get('/password',(req, res)=>{
getAuthCode(process.env.RESET_PASSWORD_POLICY_AUTHORITY, [], APP_STATES.PASSWORD_RESET, res);
});
/**
* Edit profile end point
*/
app.get('/profile',(req, res)=>{
getAuthCode(process.env.EDIT_PROFILE_POLICY_AUTHORITY, [], APP_STATES.EDIT_PROFILE, res);
});
/**
* Sign out end point
*/
app.get('/signout',async (req, res)=>{
logoutUri = process.env.LOGOUT_ENDPOINT;
req.session.destroy(() => {
//When session destruction succeeds, notify B2C service using the logout uri.
res.redirect(logoutUri);
});
});
app.get('/redirect',(req, res)=>{
//determine the reason why the request was sent by checking the state
if (req.query.state === APP_STATES.LOGIN) {
//prepare the request for authentication
tokenRequest.code = req.query.code;
confidentialClientApplication.acquireTokenByCode(tokenRequest).then((response)=>{
req.session.sessionParams = {user: response.account, idToken: response.idToken};
console.log("\nAuthToken: \n" + JSON.stringify(response));
res.render('signin',{showSignInButton: false, givenName: response.account.idTokenClaims.given_name});
}).catch((error)=>{
console.log("\nErrorAtLogin: \n" + error);
});
}else if (req.query.state === APP_STATES.PASSWORD_RESET) {
//If the query string has a error param
if (req.query.error) {
//and if the error_description contains AADB2C90091 error code
//Means user selected the Cancel button on the password reset experience
if (JSON.stringify(req.query.error_description).includes('AADB2C90091')) {
//Send the user home with some message
//But always check if your session still exists
res.render('signin', {showSignInButton: false, givenName: req.session.sessionParams.user.idTokenClaims.given_name, message: 'User has cancelled the operation'});
}
}else{
res.render('signin', {showSignInButton: false, givenName: req.session.sessionParams.user.idTokenClaims.given_name});
}
}else if (req.query.state === APP_STATES.EDIT_PROFILE){
tokenRequest.scopes = [];
tokenRequest.code = req.query.code;
//Request token with claims, including the name that was updated.
confidentialClientApplication.acquireTokenByCode(tokenRequest).then((response)=>{
req.session.sessionParams = {user: response.account, idToken: response.idToken};
console.log("\AuthToken: \n" + JSON.stringify(response));
res.render('signin',{showSignInButton: false, givenName: response.account.idTokenClaims.given_name});
}).catch((error)=>{
//Handle error
});
}else{
res.status(500).send('We do not recognize this response!');
}
});
//</ms_docref_app_endpoints>
//start app server to listen on set port
//<ms_docref_start_node_server>
app.listen(process.env.SERVER_PORT, () => {
console.log(`Msal Node Auth Code Sample app listening on port !` + process.env.SERVER_PORT);
});
//</ms_docref_start_node_server>
الخطوة 7: تشغيل تطبيق الويب
اتبع الخطوات الواردة في تشغيل تطبيق الويب لاختبار تطبيق الويب Node.js.