天天看點

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

運作效果動畫展示:

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

參考資料

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

當在複雜的環境中面臨問題,格物之道需:濁而靜之徐清,安以動之徐生。 雲中,恰是如此!

繼續閱讀