Microsoft Graph を使ってみよう : Azure ファンクション バインディング

# Azure ファンクション

[Azure Functions](https://azure.microsoft.com/ja-jp/services/functions/) は Microsoft が提供するサーバーレス開発のサービスです。多くの言語をサポートする協力な開発環境であり、Webhook の記事でも利用しました。

## Microsoft Graph 連携

Azure ファンクションでは拡張バインディングとして、以下のバインディングを提供しています。

- 認証トークンの入力バインド : 任意の Microsoft Graph API とやり取りできます
- Excel テーブルの入力バインド : Excel からデータを読み取れます
- Excel テーブルの出力バインド : Excel データを変更できます
- OneDrive ファイルの入力バインド : OneDrive からファイルを読み取ることができます
- OneDrive ファイルの出力バインド : OneDrive のファイルに書き込むことができます
- Outlook メッセージの出力バインド : Outlook で電子メールを送信できます
- Webhook バインド : Microsoft Graph からのイベントに応答できます

Microsoft Graph 拡張バインディングを使うと、接続周りのコードを減らせるため、開発効率が上がります。

# ファンクションを Graph バインドで作る

では早速入力バインドを利用してみます。Azure ファンクションは作成時にシナリオからテンプレートが選択できるようになっており、こちらに MSGraph シナリオがあるので、今回はそれを試します。

## プロファイル写真取得ファンクション

1\. [Azure ポータル](https://portal.azure.com) にログインし、新規に Windows 環境の ファンクションアプリを作成。作成したファンクションアプリを開き、「Function App の設定」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/5314ec85-2d0b-054a-666f-3f4d1b3db008.png)

2\. 拡張バインディングランタイムバージョンより「beta」を選択。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/d718b4e4-6472-8dec-2f87-dd8662b72498.png)

3\. 関数の項目より「新しい機能」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/5f1791ff-0455-0f21-a636-ed489fbc8012.png)

4\. シナリオより「MSGraph」を選択。一番上の「Microsoft Graph profile photo API」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/1fc05b8c-48ae-92c6-a300-c6773b1f43d5.png)

5\. 拡張機能のインストールを促されるので、「インストール」をクリックし、インストールが完了するまでそのまま待つ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/e3bc8bad-5fc6-446d-7839-9a4d90ec6dd7.png)

6\. 拡張機能のインストールが完了すると必要な要件を自動で検出。「App Service の認証と承認の管理」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/74281884-a83e-2502-7e8a-eb2b51fca7a6.png)

7\. 「App Service 認証」を「オン」にして、Azure Active Directory をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/a1598cf5-1c46-81dc-1fcb-91284763d110.png)

8\. 簡易をクリックして、「OK」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/eb934020-df9d-6647-887b-818fcf74e3f1.png)

9\. 「要求が認証されない場合に実行するアクション」で「Azure Active Directory でのログイン」を選択し、画面上部の「保存」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/b274f5e0-92d4-a2b7-4452-1a206995f7c8.png)

10\. 設定が再読み込みされたあと、「作成」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/0cd0c414-455b-bb2d-e635-2223b815c423.png)

11\. 関数が作成されたことを確認したら、登録したアプリケーションのマニフェストを 1 か所変更するため、再度ファンクションの名前をクリックし「認証/承認」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/3a740e43-0af3-c542-141e-9831d875ea04.png)

12\. 先ほど構成した画面が出るので、「Azure Active Directory」を選択し、「アプリケーションの管理」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/584c84a0-91f9-3fbd-3232-291992290395.png)

13\. 「マニフェスト」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/824ae3d8-e225-7bfb-c9ca-3d5d6d2b3da9.png)

14\. oauth2AllowImplicitFlow の値を false から true に変更して、「保存」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/79d7cce9-3500-10fe-5830-ed309f810445.png)

15\. 再度作成した関数に戻り、「関数の URL の取得」をクリックして URL を取得。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/aa1a939e-4f73-3091-787f-235a0d421dff.png)

16\. ブラウザを新規に開き、アドレスを入力。ログイン画面にリダイレクトされる。権限を確認して「承諾」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/a1876cc4-0e0b-b2d6-a284-dbe741222014.png)

17\. プロファイルの写真が返ることを確認。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/b5361c59-7fc5-c63b-da42-432d19403c9a.png)

### バインディングの確認

作成されたバインディングの情報を確認します。バインディングは「統合」設定か function.json ファイルで確認できます。

**統合から確認**

入力より「認証トークン」をクリックすると詳細が確認できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/325c5bc4-ac50-ecc1-8311-6db45713574c.png)

ID の設定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/45fa1f0e-f7db-a082-b925-b85d87fc62bd.png)

**ID の種類**
ID は以下の 4 タイプから選択できます。

- userFromRequest : 既定。上記で試した通りログインした ID で実行。
- userFromId - 指定された ID を使用
- userFromToken - 指定したトークンを使用
- clientCredentials - アプリケーション認証

### アプリケーション認証を試す

ユーザー委任ではなく、アプリケーション認証を試してみます。

1\. 統合の入力より「認証トークン」を選択し、ID で「クライアント資格情報」を選択し「保存」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/a50b9297-ceda-788b-8046-337d66a294ca.png)

2\. 一旦他は変更せず再度、関数の URL にアクセス。エラーとなる。これはアプリケーション認証であるが /me を使っているため。

```json:エラー
{
  "error": {
    "code": "BadRequest",
    "message": "Current authenticated context is not valid for this request. This occurs when a request is made to an endpoint that requires user sign-in. For example, /me requires a signed-in user.  Acquire a token on behalf of a user to make requests to these endpoints.  Use the OAuth 2.0 authorization code flow for mobile and native apps and the OAuth 2.0 implicit flow for single-page web apps.",
    "innerError": {
      "request-id": "6f61f89c-f8ca-48c8-adfa-e5b42140380d",
      "date": "2018-05-22T03:32:21"
    }
  }
}
```

3\.　関数に戻り、コードを変更。

```csharp:C#
using System.Net; 
using System.Net.Http; 
using System.Net.Http.Headers; 

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, string graphToken, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");    
    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken);
    return await client.GetAsync("https://graph.microsoft.com/v1.0/users/b04001fc-ec8e-4000-92d8-f1729b6a06e4/photo/$value");
}
```

4\. 再度関数の URL にアクセス。またエラーが表示される。これはアプリケーションの権限登録が足りないため。

```json:エラー
{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access is denied. Check credentials and try again.",
    "innerError": {
      "request-id": "1cd0fd4b-9be1-4784-b4cb-1d9de154bc04",
      "date": "2018-05-22T03:33:34"
    }
  }
}
```
5\. ファンクションより「認証/承認」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/deaa2271-2bb6-8412-19ab-73c334edd791.png)

6\. 構成済の「Azure Active Directory」を選択し、「アクセス許可の管理」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/b1b95fa2-ec23-670d-19e7-917865026569.png)

7\. 「Windows Azure Active Directory」を選択し「Read all user's full profiles」をチェックして「保存」

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/31208d7a-d065-4f5c-6f6c-3ec2ff0d1179.png)

8\. 「アクセス許可の付与」をクリックして管理者同意を実行。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/40cfbe22-9082-6282-0b6f-e3a6e75afec5.png)

9\. 許可実行後、再度関数の URL にアクセスして、写真が取れることを確認。

## Webhook 関連のファンクション

Webhook 関連のファンクションは、現在不具合があり、特定の手順を踏む必要があります。

1\. 新しいファンクションを作成し、ランタイムを beta に変更。新規の関数より「MSGraph」シナリオを選択し、「Outlook message webhook creator」を選択。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/d3e2dcd9-98d5-d8df-def6-07cacd8114f0.png)

2\. 先ほどと同様の手順で Azure AD にアプリケーション設定をする。またマニフェストも忘れずに更新。ここで注意点は以下のように、「要求が認証されない場合に実行するアクション」で「匿名要求を許可する」を選択し、画面上部の「保存」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/ca1ae017-85f6-e168-b718-090df006138b.png)

3\. そのままファンクションを作成。作成されたら「関数の URL の取得」より URL をコピー。 新しくブラウザを開き、一旦コピーした URL を張り付け、ホスト名以降を .auth/login/aad に変更。

https://msgraphdemo02.azurewebsites.net/api/OutlookM... の場合
https://msgraphdemo02.azurewebsites.net/.auth/login/aad

4\. サインインをして認可で許可を実行後、再度ファンクションの URL にアクセス。特に画面に結果に帰らない。

5\. 同じファンクションで新しい機能を追加。今度は「Outlook message webhook handler」を選択。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/ad7cfd4c-3aad-5b65-53ca-02ffa315da6b.png)

6\. 作成された関数の画面を開き、ログを展開。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/66b85bb8-ccac-d12f-316d-85fb3c9a7bc2.png)

7\. 件名に「[DEMO] Azure Functions」を含むメールを送信してログを確認。しばらくすると以下のように、メールが受信できた旨がログされる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/f118de9a-9014-1609-78ea-5a19d734df3b.png)

# まとめ

以前紹介したように、本来 Webhook を使うと通知を受けたのち、実際のデータを取得する必要がありますが、ファンクションのバインディングはそこをうまく処理してくれます。

バインディングを使うことで処理が隠される分、実際にどう動作しているか理解する必要はありますが、とても完結にコードを記述することが出来ます。

[目次に戻る](https://qiita.com/kenakamu/items/6a1ca508dc093779eefa)

# 参照

[Azure Functions](https://azure.microsoft.com/ja-jp/services/functions/) 
[Azure Functions における Microsoft Graph のバインド](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-microsoft-graph#auth-token)
[Azure Functions and Microsoft Graph : Build 2018 (動画:英語)](https://www.youtube.com/watch?v=D7kGwrp68eI)