NodeJS对接Microsoft Graph API操作用户Outlook日历事件(二)

通过Microsoft Identity Platform获取访问令牌,包括用户认证和无用户认证方式。

前言

一开始是通过调用微软的https://login.microsoftonline.com,让用户自己输入微软账号密码完成登录认证,认证之后重定向回网页继续操作,后面客户说不一定所有人都记得自己的微软账号密码,要求改成自动登录,之后就改成了完全无用户的认证,确实实现了group内所有成员的信息获取,但是客户考虑这样权限太大,可访问的信息太多,所以最后还是改成了通过用户认证,只不过认证用户是group管理员,然后操作group内其他成员的outlook事件。

所以总结下来这次实现了以下三次认证方式:

  1. 通过Microsoft 标识平台 ,用户完成账号登录后,获取访问令牌并重定向返回。
  2. 使用Client Secret value,完成无用户的身份认证。
  3. 使用代表用户账号,无需用户手动登录,自动完成身份认证。

一,通过Microsoft 标识平台 ,用户完成账号登录后,获取访问令牌并重定向返回。

这里以官方的angularDemo来介绍需要用户手动入力账号密码完成认证的情况举例,从github下载代码,简单配置后(npm install)运行结果如下

上图就是通过用户手动输入微软账号密码来实现身份认证,认证完成之后如下图

认证成功如上图所示

这里比较关键的认证处理代码如下

一个是通过引入 import { MsalService } from '@azure/msal-angular',来调用loginPopup方法,传入OAuthSettings实现认证

  async signIn(): Promise<void> {
    let result = await this.msalService.loginPopup(OAuthSettings)
      .catch((reason) => {
        this.alertsService.addError('Login failed', JSON.stringify(reason, null, 2));
      });

    if (result) {
      this.authenticated = true;
      this.user = await this.getUser();
    }
  }


  // access Token 获取 
  async getAccessToken(): Promise<string> {
    let result = await this.msalService.acquireTokenSilent(OAuthSettings)
      .catch((reason) => {
        this.alertsService.addError('Get token failed', JSON.stringify(reason, null, 2));
      });

    if (result) {
      return result.accessToken;
    }

    // Couldn't get a token
    this.authenticated = false;
    return null;
  }

 这里是获取accessToken注册import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';服务,进而调用Microsoft Graph API获取信息。

    this.graphClient = Client.init({
      authProvider: async (done) => {
        // Get the token from the auth service
        let token = await this.authService.getAccessToken()
          .catch((reason) => {
            done(reason, null);
          });

        if (token)
        {
          done(null, token);
        } else {
          done("Could not get an access token", null);
        }
      }
    });

官方的NodeJs Demo使用之前要修改example.env配置信息并npm install,关键代码如下,

二,使用Client Secret value,完成无用户的身份认证。

无用户认证非常关键地方是使用到CLIENT_SECRET ,就是之前的文章提到的secret value。

还有之前Microsoft Azure注册的API permission必须追加 application permissions相关权限。

第一步获取accessToken,这里使用axios模块发起http请求,nodeJS关键代码

import axios from 'axios';
const querystring: any = require('querystring');

const TENANT_ID = 'xxxx'
const CLIENT_ID = 'xxxx';
const CLIENT_SECRET = 'xxxx';

(async () => {

    const qs = querystring.stringify({
        client_id: CLIENT_ID,
        client_secret: CLIENT_SECRET,
        scope: 'https://graph.microsoft.com/.default',
        grant_type: 'client_credentials'
    });

    const url = `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`;

    const result = await axios.request({
        url,
        method: "POST",
        data: qs
    });

    const access_token = result.data.access_token;
    console.log(access_token);
})();

 不使用@microsoft/microsoft-graph-client的情况下,通过access token 调用Microsoft Graph API

import axios from 'axios';
const ACCESS_TOKEN = 'xxxx';

(async () => {
    const itemList = [];
    const url = 'https://graph.microsoft.com/v1.0/groups';
    let page = url;

    do {
        const result = await axios.request({
            headers: {
                'Authorization': `Bearer ${ACCESS_TOKEN}`
            },
            url: page,
            method: "GET"
        });

        itemList.push(...result.data.value);
        page = result.data["@odata.nextLink"];

    } while (page);

    console.log(itemList);

})();

使用@microsoft/microsoft-graph-client的情况下,通过access token 调用Microsoft Graph API

var graph = require('@microsoft/microsoft-graph-client');

// graph.Client注册
function getAuthenticatedClient(accessToken) {
  // Initialize Graph client
  const client = graph.Client.init({
    // Use the provided access token to authenticate
    // requests
    authProvider: (done) => {
      done(null, accessToken);
    }
  });

  return client;
}

module.exports = {
  getUserDetails: async function(accessToken,userPrincipalName) {
    const client = getAuthenticatedClient(accessToken);

    //const user = await client.api('/me')
    const user = await client.api(`/users/${userPrincipalName}`)
      .select('displayName,givenName,jobTitle,mail,mobilePhone,officeLocation,preferredLanguage,surname,userPrincipalName,id,mailboxSettings')
      .get();
    return user;
  },
};

3.使用代表用户账号,自动完成身份认证。

相较于之前的无用户认证,只要修改的代码如下

import axios from 'axios';
const querystring: any = require('querystring');

const TENANT_ID = 'xxxx'
const CLIENT_ID = 'xxxx';
//const CLIENT_SECRET = 'xxxx';
const USER_ID = 'xxxx';
const USER_PASSWORD = 'xxxx';

(async () => {

    const qs = querystring.stringify({
        client_id: CLIENT_ID,
        username:USER_ID ,
        password:USER_PASSWORD,
        grant_type: 'password'
    });

    const url = `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`;

    const result = await axios.request({
        url,
        method: "POST",
        data: qs
    });

    const access_token = result.data.access_token;
    console.log(access_token);
})();

以上就是三种认证方式,关于获取的access Token 可以通过JWT解析来查看返回的信息,比如通过无用户认证获取的access Token解析如下,使用用户获取的access Token会稍微有点不同,如下第二张图

无用户认证的access Token

 有用户认证的access Token

猜你喜欢

转载自blog.csdn.net/bai_ye_/article/details/115027298
今日推荐