• 【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);
     
    最后,实现 /auth 和 /redirect 接口代码 (/auth 是登录AAD的入口,登录成功后由AAD回调/redirect接口,输出Access Token内容
    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

  • 相关阅读:
    Android游戏开发22:Android动画的实现J2me游戏类库用于Android开发
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第三部分,完整代码)
    使用OGR创建dxf格式矢量数据
    mysql 数据库引擎 MyISAM InnoDB 大比拼 区别
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第二部分)
    mysql 更改数据库引擎
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第一部分)
    android 数字键盘使用
    MySQL Innodb数据库性能实践
    eclipse : Error while performing database login with the driver null
  • 原文地址:https://www.cnblogs.com/lulight/p/16357246.html
Copyright © 2020-2023  润新知