Microsoft Graph(Microsoftクラウドサービスの統合API)の使い方

Microsoft Graph を使うと、OneDrive (for Business) や SharePoint, Outlook, Teams 等を含む多くの Microsoftクラウド製品を、標準化された REST API 経由で操作できる。 developer.microsoft.com

何ができるかはの詳細は上記リンク先に記載されているが、以下のようなリソースの主要な操作はだいたい行うことができる。

今回は例として、O365を契約している前提で、OneDrive for Business からファイルを取得する場合の手順を説明する。 利用する際は、REST API を直接叩くこともできるが、SDK が提供されている言語の場合は、SDK を使うのが楽で良い。提供されている SDK は以下のとおり。今回は、.NET SDK を利用する。

目次

1. アプリの登録

事前に、Graph にアクセスするアプリケーションを認証基盤側に登録する必要がある。

1.1 アプリの作成

Azure AD の認証エンドポイントには、v1.0 と v2.0 の 2 つがあり、それぞれアプリ登録を行う場所が異なる(v1.0 と v2.0 の違いについては後述)。今回は v1.0 を利用するので、Azure Portal の Azure AD 管理画面からアプリ作成を行う。

詳細な手順については、以下を参考にすると良い。 docs.microsoft.com

「アプリケーションの種類」は「Web アプリ/API」を選択する。また、作成したアプリの画面に表示される アプリケーションID が、後ほど使う Client ID となるので、メモしておく。

f:id:nosunosu:20180626121314p:plain

1.2 Client Secret の生成

アプリ作成後には、メニューからキーを生成しておく。これが後ほど用いるClient Secretとなるので、同じくメモしておく。

f:id:nosunosu:20180626121325p:plain

1.3 アプリへの権限付与

さらに、作成したアプリに対して、Graph で利用したいリソースへのアクセス許可を付与する。 アプリの「設定」から「必要なアクセス許可」→「追加」と進み、API として「Microsoft Graph」を、アクセス許可としては「アプリケーションのアクセス許可」から「Read all groups」を選択して保存する。

f:id:nosunosu:20180626121338p:plain

そのうえで、「必要なアクセス許可」の画面から再度「Microsoft Graph」を選択し、「アクセス許可の付与」→「はい」を選択する。

なお、あとから権限を削除したい場合も、削除したいアクセス許可のチェックを外して保存したあとに、同様に「アクセス許可の付与」を再度行う必要があるので注意する。

行いたい処理に対して、どのようなアクセス許可が必要かは、以下のドキュメントで確認できる。

アクセス許可 - ドキュメント - Microsoft Graph

2. アプリ実装

2.1 認証の流れ

アプリの登録が終わったら、Visual Studio でコンソールアプリを作成し、以下の NuGet パッケージをインストールする。

  • Microsoft.IdentityModel.Clients.ActiveDirectory
  • Microsoft.Graph

事前準備で作成したアプリの Client ID, Client Secret を使って認証トークンを Azure AD から取得し、そのトークンを使って認証する Graph 用クライアントのインスタンスを作成する。

// TODO: "hogehoge"部分を、アクセス先となる Azure AD テナントの名前に置き換える
var authority = "https://login.microsoftonline.com/hogehoge.onmicrosoft.com";
var authContext = new AuthenticationContext(authority, null);

// TODO: Azure Portal で作成したアプリの Client ID, Client Secret に置き換える
var clientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
var clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
var clientCredential = new ClientCredential(clientId, clientSecret);

// 指定したリソースへのアクセス権限を持った認証トークンを取得する
var graphResourceUri = "https://graph.microsoft.com";
var authResult = await authContext.AcquireTokenAsync(graphResourceUri, clientCredential);
var accessToken = authResult.AccessToken;

// リクエスト送信時に認証トークンを利用するように設定した、GraphServiceClient のインスタンスを作成する
var graphServiceClient = new GraphServiceClient(
    new DelegateAuthenticationProvider((requestMessage) => {
        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
        return Task.FromResult(0);
    })
);

あとは、作成した GraphServiceClientインスタンスを使って、Microsoft Graph へのリクエストを送信する。

// Group のリストを取得
var groups = await graphClient.Groups.Request().GetAsync();

// 各 Group のデフォルトの Drive と、Drive のルートにあるファイル・フォルダのリストを取得する
foreach(var group in groups) {
    Console.WriteLine($"Group Name: {group.DisplayName}, Group ID: {group.Id}");

    var drive = await graphClient.Groups[group.Id].Drive.Request().GetAsync();
    Console.WriteLine($"Drive Name: {drive.Name}, Drive ID: {drive.Id}");

    var rootItems = await graphClient.Drives[drive.Id].Root.Children.Request().GetAsync();
    Console.WriteLine($"Items in the root folder:");
    foreach(var item in rootItems) {
        Console.WriteLine($"  - {item.Name}");
    }
}

2.2 例外ハンドリング

GraphServiceClientServiceException 型の例外を投げる。ServiceException の持つ IsMatch() を使うと、エラーの種別を判別することができる。

try { ... }
catch(ServiceException ex) {
    if(ex.IsMatch(GraphErrorCode.ItemNotFound.ToString())) {
        Console.WriteLine("指定したファイルが見つかりませんでした。");
    }
}

この場合、ItemNotFound のエラーなので、その旨のエラーメッセージを出力している。

その他 GraphErrorCode が持つエラーの種別については、以下に一覧が記載されている。

https://developer.microsoft.com/en-us/graph/docs/concepts/errors

3. 補足

3.1 Web アプリとネイティブアプリでの認証の違い

少し話は脱線するが、Web アプリや Web API から Graph にアクセスする場合と、デスクトップ・スマホなどネイティブアプリから直接 Graph にアクセスする場合で、用いるべき認証の方式が異なる。

前者の場合は、Client IDClient Secretの組み合わせで認証される"Service Principal"と呼ばれるアプリを示すアカウントの権限を用いて、Graph にアクセスすることができる。一方後者の場合は、Client Secret を安全に秘匿することができないため、実際にアプリを使うユーザが自身のアカウントを使って Azure AD の画面からログインすることで、そのユーザ自身の権限を用いて Graph にアクセスする。

今回のサンプルでは、説明の都合上コンソールアプリで Service Principal を利用しているが、実利用においては正しく使いわけること!

3.2 Azure AD v1.0 と v2.0 の違い

Azure AD v1.0 と v2.0 の違いは以下に詳しく説明されている。 docs.microsoft.com

大きな違いとしては、以下のような点がある。

  • v1.0 は Azure AD アカウントのみをサポートしていたのに対して、v2.0 ではさらに Microsoft Account もサポートしている
  • 認証に使うライブラリも、v1.0 は従来の ADAL を利用するのに対して、v2.0 では MSAL と呼ばれる、新しい認証ライブラリを使う