【Azure 應用服務】NodeJS Express + MSAL 應用實現AAD登入並獲取AccessToken -- cca.acquireTokenByCode(tokenRequest)

2022-06-09 06:02:17

問題描述

在上一篇博文 「【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