M365関連 技術

JavaScriptでMicrosoftGraphAPIを使う(Express&MSAL版)

GraphAPIをJavaScriptから呼び出そうとした際に色々と手間取ったので、そのメモです
今回はNodeJSのExpressと@azure/msal-nodeを使用します
以下のMSのドキュメントサイトを参考に実装しています

MSサイト
チュートリアル: Node.js コンソール デーモン アプリで Microsoft Graph を呼び出す - Microsoft identity platform | Microsoft Learn
チュートリアル: Node.js コンソール デーモン アプリで Microsoft Graph を呼び出す - Microsoft identity platform | Microsoft Learn

このチュートリアルでは、Microsoft Graph を呼び出すためのコンソール デーモン アプリを作成します。

続きを読む

アプリを作成する

Azure上で今回使用するアプリを作成します。「Azure Active Directory」>「アプリの登録」>「新規作成」の順にクリックし、アプリケーション名を任意の値、アカウントの種類はシングル、リダイレクトURIを空欄で作成します

登録したアプリの設定

使用するAPIアクセス許可を付与する

必要な権限を付与する

今回は全ユーザーの取得と対象ユーザーの予定取得をするために、【User.Read.All】と【Calendars.Read】のどちらの権限もアプリケーション権限として付与します

作成したアプリの APIのアクセス許可 > アクセス許可の追加 > Microsoft Graph > アプリケーションの許可 > User.Read.All を検索窓に入力し、検索結果のUser配下の方にチェックを付ける > アクセス許可の追加 の順にクリックしていく

【Calendars.Read】も上記画像の【User.Read.All】と同様に権限を付与します

管理者の同意を付与する

今回はアプリケーション権限を付与するため、管理者の同意が必要となるためそれを付与します

赤枠で囲っている~~に管理者の同意を与えますをクリック
赤枠で囲った箇所のように~~に付与されましたとなればOK

シークレットキーを設定

API呼び出し時の認証で使用するシークレットキーを生成します

作成したアプリの 証明書とシークレット > クライアントシークレットタブ > 新しいクライアント シークレット > 説明欄に任意の名前を入れる > 追加 の順にクリックしていく
クライアントシークレットを作成すると画像のようにクリップボードにコピーができるボタンがあるのでそれをクリックして、どこかに保存しておく。時間がたつとボタンが消えてクライアントシークレットの値がわからなくなるので注意が必要

NodeJSのプロジェクトの設定

プロジェクトに必要なものをインストールする

任意のプロジェクトファイル配下で以下のコマンドを実行し、プロジェクトを作成します
今回はRestAPI作成で使用する【Express】とHTTP クライアントである【axios】、GraphAPIのトークン取得時に使用する【@azure/msal-node】(MSALライブラリ)をインストールします。今回は必要最低限のものしかインストールしていないので、必要に応じて適宜追加でインストールしてください

npm init
npm install --save express axios @azure/msal-node

認証に必要なデータを設定

auth.jsというファイルを作成し、そこに認証に必要なデータを記載していきます
各項目については以下のMSサイトを参考にしてください

MSサイト
チュートリアル: Node.js コンソール デーモン アプリで Microsoft Graph を呼び出す - Microsoft identity platform | Microsoft Learn
チュートリアル: Node.js コンソール デーモン アプリで Microsoft Graph を呼び出す - Microsoft identity platform | Microsoft Learn

このチュートリアルでは、Microsoft Graph を呼び出すためのコンソール デーモン アプリを作成します。

続きを読む

const msal = require('@azure/msal-node');

const TENANT_ID = "Azureのアプリ上から取得できるテナントID";
const CLIENT_ID = "Azureのアプリ上から取得できるクライアントID";
const CLIENT_SECRET = "本記事内で取得したクライアントシークレットキーの値";

// 実行環境によっては変更が必要なため以下のMSのサイト記事を参照のこと
const AAD_ENDPOINT = "https://login.microsoftonline.com";
const GRAPH_ENDPOINT = "https://graph.microsoft.com";

const msalConfig = {
    auth: {
        clientId: CLIENT_ID,
        authority: AAD_ENDPOINT + '/' + TENANT_ID,
        clientSecret: CLIENT_SECRET,
    }
};

const tokenRequest = {
    scopes: [GRAPH_ENDPOINT + '/.default'],
};

const apiConfig = {
    uri: GRAPH_ENDPOINT,
};

const cca = new msal.ConfidentialClientApplication(msalConfig);

async function getToken(tokenRequest) {
    return await cca.acquireTokenByClientCredential(tokenRequest);
}

module.exports = {
    apiConfig: apiConfig,
    tokenRequest: tokenRequest,
    getToken: getToken
};

GraphAPIを呼び出す

次に実際にGraphAPIを呼び出し用の関数を作成します

async function callGraphAPI(endpoint) {
    console.log(`endPointURL:${endpoint}`);
    const authResponse = await auth.getToken(auth.tokenRequest);

    const options = {
        headers: {
            Authorization: `Bearer ${authResponse.accessToken}`
        }
    };

    try {
        const response = await axios.get(endpoint, options);
        console.log(response.data);
        return response.data;
    } catch (error) {
        console.log(error)
        return error;
    }
}

では実際にユーザー情報を取得するAPIを作成してみます
今回はPostmanを使用して検証しています

app.get("/getAllUser", (req, res) => {
    var apiURL = "/v1.0/users";
    var select = "";
    if(req.query.select != null)  {
        select = `$select=${req.query.select}`
    }

    if(select != "") {
        apiURL = `${apiURL}?${select}`;
    }

    callGraphAPI(`${auth.apiConfig.uri}${apiURL}`).then(result => {
        res.json({ responseData: result });
    });
});
ユーザー情報の取得に成功しました

対象ユーザーのイベント一覧を取得します

app.get("/getCalendarView", (req, res) => {
    var targetId = req.query.targetId;
    var startDay = req.query.startDay;
    var endDay = req.query.endDay;
    var select = "";
    if(req.query.select != null)  {
        select = `$select=${req.query.select}`
    }

    // 必須となるデータが未定義の場合
    if(targetId == null || startDay == null || endDay == null) {
        res.status(400).send("パラメータが不正です");
        return;
    }

    var apiURL = `/v1.0/users/${targetId}/calendarView?startDateTime=${startDay}T00:00:00&endDateTime=${endDay}T23:59:59`;

    if(select != "") {
        apiURL = `${apiURL}&${select}`;
    }

    callGraphAPI(`${auth.apiConfig.uri}${apiURL}`).then(result => {
        res.json({ responseData: result });
    });
});
こちらも問題なく情報の取得ができました

最後に

今回使用したNodeJSのプロジェクトファイルやJSファイルを以下のGitHubにアップしているので、参考にしてください

サンプル
BlogSampleCodeProjects/MicrosoftGraphAPI_NodeJS_Express_MSAL at main · nasuton/BlogSampleCodeProjects · GitHub
BlogSampleCodeProjects/MicrosoftGraphAPI_NodeJS_Express_MSAL at main · nasuton/BlogSampleCodeProjects · GitHub

Project for sample code used in the blog.(Blogで記載しているサンプルコード ...

続きを読む

-M365関連, 技術
-, ,