【Azure 应用服务】NodeJS Express + MSAL 应用实现AAD登录并获取AccessToken -- cca.acquireTokenByCode(tokenRequest)
问题描述
在上一篇博文 “【Azure 应用服务】NodeJS Express + MSAL 应用实现AAD集成登录并部署在App Service Linux环境中的实现步骤”中,实现了登录,并获取登录用户在AAD中的个人信息,但是没有一个显示的方法输出所获取到的Access Token,则通过新建Express项目,加载MSAL的代码实现此目的。
实现步骤
第一步:创建 NodeJS Express项目,并添加@azure/msal-node 项目包
前提条件:安装 Node.js 和 VS Code
使用npm安全express项目生成器
npm install -g express-generator
在当前目录在生成 express项目默认文件
express --view=hbs
开始生成项目文件
npm install
安装MSAL package
npm install --save @azure/msal-node
项目生成后的完整路径
myExpressWebApp/ ├── bin/ | └── wwww ├── public/ | ├── images/ | ├── javascript/ | └── stylesheets/ | └── style.css ├── routes/ | ├── index.js | └── users.js ├── views/ | ├── error.hbs | ├── index.hbs | └── layout.hbs ├── app.js └── package.json
第二步:在 app.js 中添加 MSAL object,添加 '/auth' 接口登录AAD并获取Access Token
引入 msal 对象
const msal = require('@azure/msal-node');
配置AAD Authentication 参数 clientId, authority 和 clientSecret (与上一篇博文中第一步相同, 也需要添加 http://localhost:3000/redirect 在 AAD注册应用的Redirect URIs中)。
// Authentication parameters const config = { auth: { clientId: " Enter_the_Application_Id_Here", authority: "https://login.partner.microsoftonline.cn/<#Enter_the_Tenant_Info_Here>", clientSecret: "xxxxxx.xxxxxxxxxxxxxxxxx" #Enter_the_Client_Secret_Here }, system: { loggerOptions: { loggerCallback(loglevel, message, containsPii) { console.log(message); }, piiLoggingEnabled: false, logLevel: msal.LogLevel.Verbose, } } }; const REDIRECT_URI = "http://localhost:3000/redirect";
然后根据上一步的config参数初始化 msal confidential client applicaiton对象
// Initialize MSAL Node object using authentication parameters const cca = new msal.ConfidentialClientApplication(config);
app.get('/auth', (req, res) => { // Construct a request object for auth code const authCodeUrlParameters = { scopes: ["user.read"], redirectUri: REDIRECT_URI, }; // Request auth code, then redirect cca.getAuthCodeUrl(authCodeUrlParameters) .then((response) => { res.redirect(response); }).catch((error) => res.send(error)); }); app.get('/redirect', (req, res) => { // Use the auth code in redirect request to construct // a token request object const tokenRequest = { code: req.query.code, scopes: ["user.read"], redirectUri: REDIRECT_URI, }; // Exchange the auth code for tokens cca.acquireTokenByCode(tokenRequest) .then((response) => { res.send(response); }).catch((error) => res.status(500).send(error)); });
完整 app.js 代码为:
var createError = require('http-errors'); var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); var logger = require('morgan'); var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users'); const msal = require('@azure/msal-node'); // Authentication parameters const config = { auth: { clientId: " Enter_the_Application_Id_Here", authority: "https://login.partner.microsoftonline.cn/<#Enter_the_Tenant_Info_Here>", clientSecret: "xxxxxx.xxxxxxxxxxxxxxxxx" #Enter_the_Client_Secret_Here }, system: { loggerOptions: { loggerCallback(loglevel, message, containsPii) { console.log(message); }, piiLoggingEnabled: false, logLevel: msal.LogLevel.Verbose, } } }; const REDIRECT_URI = "http://localhost:3000/redirect"; // Initialize MSAL Node object using authentication parameters const cca = new msal.ConfidentialClientApplication(config); var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'hbs'); app.use(logger('dev')); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', indexRouter); app.use('/users', usersRouter); app.get('/auth', (req, res) => { // Construct a request object for auth code const authCodeUrlParameters = { scopes: ["user.read"], redirectUri: REDIRECT_URI, }; // Request auth code, then redirect cca.getAuthCodeUrl(authCodeUrlParameters) .then((response) => { res.redirect(response); }).catch((error) => res.send(error)); }); app.get('/redirect', (req, res) => { // Use the auth code in redirect request to construct // a token request object const tokenRequest = { code: req.query.code, scopes: ["user.read"], redirectUri: REDIRECT_URI, }; // Exchange the auth code for tokens cca.acquireTokenByCode(tokenRequest) .then((response) => { res.send(response); }).catch((error) => res.status(500).send(error)); }); // catch 404 and forward to error handler app.use(function(req, res, next) { next(createError(404)); }); // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); }); module.exports = app;
运行效果动画展示:
参考资料
NodeJS Express + MSAL 应用实现AAD集成登录并部署在App Service Linux环境中的实现步骤:https://www.cnblogs.com/lulight/p/16353145.html
Tutorial: Sign in users and acquire a token for Microsoft Graph in a Node.js & Express web app: https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-nodejs-webapp-msal
Example: Acquiring tokens with ADAL Node vs. MSAL Node:https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-node-migration#example-acquiring-tokens-with-adal-node-vs-msal-node
当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!