Salesforce から Microsoft Graph API を利用してみました

# Salesforce から Microsoft Graph API をアクセスする方法
現在私の働いている会社では Salesforce を結構カスタマイズして使っておりまして、いくつかの方法で Salesforce と Sharepoint や Office アプリと連携させています。今回は、そのうちの Salesforce の Apex から Microsoft Graph API をアクセスする方法を紹介したいと思います。例えば Salesforce のレコードページから Excel で帳票を出力したり、Sharepoint 内の Excel ファイルから為替データを取り出したりすることができます。
全体の流れは次のようになります。各種設定が必要ですので、Salesforce のシステム管理者であることと、Microsoft 365 管理センターでアプリケーション登録ができる権限が必要です。あと、今回は Graph API の使い方やアクセス権限についてはご理解いただいている前提で、お話進めさせていいただきます。

1. Microsoft365 にアプリケーションの登録
2. Salesforce に Microsoft のサイトを登録
3. Salesforce に認証プロバイダの登録
4. Salesforce に指定ログイン情報の登録
5. Salesforce Apex から Graph API の呼び出し
6. SFDXと新しい組織作成時の手順

## 1. Microsoft365 にアプリケーションを登録

* Microsoft365 管理センターにログインして、左側「管理センター」のメニューから「ID」を選択し Microsoft Entra 管理センターに遷移します。
* 「ホーム」のページに「テナントID」が表示されていますので控えておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/d3beb017-d7c6-4194-fdfe-f9d293f3cd64.png)

* 次に「アプリケーション」「アプリの登録」を選択します
* 「追加」を選択して「アプリケーションの登録」を行います。ここでは「名前」のみ指定してください。リダイレクト URI は後ほど設定します。仮に「Salesforfce ID Provider」という名前にしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/9ff18023-c5ba-5735-a301-5eca5e22445c.png)

登録したアプリケーションを開きます。「アプリケーション(クライアント)ID」は後ほど使いますので控えておいてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/31d92eac-333b-cf6e-27d7-48be2af09f43.png)

左側「証明書とシークレット」を選んで「新しいクライアントシークレット」でクライアントシークレットを作成します。作成したクライアントシークレットの「値」をコピーして控えておいてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/c8a7d0d7-0ca3-09dc-fc99-97665f2eb5ad.png)

必要な GraphAPIのアクセス設定をしてください。下は一例ですが、offline_access と openid は必要なようです。また、管理者の同意が必要なアクセス権の場合は、同意を与える必要があります。下の画面から切れていますが、右側に「状態」という項目があるので、緑色のチェックが付いていることを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/3b7d3f7d-dc00-5830-9ad8-1f079cd15ffb.png)
これから Salesforce の設定に移りますが、後ほど追加作業がありますのでMicrosoft Entra 管理センター画面はそのまま開いておきます。

## 2. Salesforce に Microsoft のサイトを登録
Salesforce から外部のサイトにアクセスするには設定が必要です。Salesforce の設定から「セキュリティ」「リモートサイトの設定」を選び、「新規リモートサイト」を作成します。次の２つを登録してください。
* Microsoft_Graph: https://graph.microsoft.com
* Microsoft_Login: https://login.microsoftonline.com
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/651ed48a-35b7-5999-3727-9cb9048aa3e5.png)
## 3. Salesforce に認証プロバイダの登録
次に Graph API にアクセスするための認証プロバイダを作成します。Salesforce　設定から「ID」「認証プロバイダー」を選び、「新規」ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/ae9d62a5-ecb2-b5f9-aa13-fdb8d3a67b21.png)
* プロバイダータイプ：Open ID Connect
* 名前：ここでは ”GraphAPI接続” としておきます
* URL接尾辞：ここでは “GraphAPI” としておきます
* コンシューマ鍵：先ほど控えた「アプリケーション(クライアント)ID」を指定します
* コンシューマの秘密：先ほど控えたクライアントシークレットの「値」を指定します
* 承認エンドポイント URL：「テナントID」を先ほど控えたものに置換してください
https://login.microsoftonline.com/(テナントID)/oauth2/v2.0/authorize
* トークンエンドポイントURL:
https://login.microsoftonline.com/(テナントID)/oauth2/v2.0/token
* ユーザー情報エンドポイントURL：空
* Proof Key for Code Exchange (PKCE) 拡張を使用：チェック有
* トークン発行者：空
* デフォルトの範囲：https://graph.microsoft.com/.default offline_access openid
* ヘッダーでアクセストークンを送信：チェック有
* ヘッダーでクライアントログイン情報を送信：チェック無
* SOAP API応答にコンシューマの秘密鍵を含める：チェック有
* その他は空欄です

保存すると、下のほうに「Salesforce 設定」というタイトルでURLが４つ表示されます。そのうちの「コールバック URL」を控えてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/bc49c176-69b3-272c-1b82-770a716a155d.png)

Entra 管理センターに戻って、「認証」から 「Web リダイレクト URI」 に「URIの追加」し、上のコールバック URL を指定します。Salesforce で開発をするとき、本番環境のほかに、サンドボックスやスクラッチ組織を作ると思いますが、Salesforce 組織を作ったときはコールバック URI が変わりますので、都度こちらに追加していきます。
## 4. Salesforce に指定ログイン情報の登録
Salesforce　設定から「セキュリティ」「指定ログイン情報」を選び、新規のドロップダウンメニューから「新規(従来)」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/ce259ecd-3119-15a8-b245-fce6e418919a.png)

* 表示ラベル：なんでもよいです
* 名前：ここでは “msgraph” としておきます。Apex からこの名前を参照しますので、控えておきます
* URL：https://graph.microsoft.com/v1.0
* 証明書：空
* ID種別：指定ユーザ
* 認証プロバイダ：先ほど作成した認証プロバイダを指定します（”GraphAPI接続”）
* 範囲：空
* その他デフォルトのままです

保存すると、Graph API へ認証にいき、成功すると認証状況が「認証済み」となります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/6334122c-72b5-2166-198e-1fd21bad18f4.png)

## 5. Salesforce Apex から Graph API の呼び出し
あとは Apex から HttpRequest を送るのですが、Uri は “callout:<指定ログインの名前>” で始まるようになります。その後ろに、指定ログインで指定した URI につづく部分を加えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/897bb2b7-fba8-699f-1fe3-ffe256007817.png)

下は SharePoint 内の Excel ブックにセッションを作成している例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/4937f6ca-6f6a-fee2-f505-2a2be3ed720a.png)
## 6. SFDXと新しい組織作成時の手順
SFDX をご利用の場合、今回の設定を pull すると、次のようなファイルに保存されます。チェックインする前に、認証プロバイダ (AuthProvider) の <consumerSecret> を Placefolder のような仮値に変更してくのがよいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/f648046f-bb37-1d7f-c592-40636c2dea87.png)
新しくサンドボックスやスクラッチ組織を作った時、保存しておいた情報を depoly/push すれば今回の接続周りの設定はほぼ再現されますが、次の手順は組織を作るたび必要です：
* 認証プロバイダの設定から、Placefolder としておいた秘密鍵を設定します (Entra 側のアプリケーションは共通して使えますので、セキュリティ上問題なければ秘密鍵も共通で大丈夫です)
* コールバック URI は組織毎に異なりますので、都度 Entra 管理画面から URI を追加します
* 指定ログイン情報を一旦編集モードにして、そのまま保存します。この時、新しい組織の認証が行われます。

本日は以上です。無事 Apex から Graph API にアクセスできましたでしょうか。ご意見ご感想ご指導など、お待ちしております。