Microsoft Graph の操作に関するベスト プラクティス

この記事では、Microsoft Graph の学習、アプリのパフォーマンスの向上、エンド ユーザーのアプリケーションの信頼性の向上など、アプリケーションが Microsoft Graph を最大限に活用できるようにするために適用できるベスト プラクティスについて説明します。

Graph エクスプローラーを使用して API を理解する

Microsoft Graph で利用できるデータについての理解を深める最も良い方法は、Graph エクスプローラーを使用してみることです。 Graph エクスプローラーを使用すると、CRUD をすべてサポートした REST 要求を作成し、HTTP 要求ヘッダーを適合させて、データ応答を確認できます。 Graph エクスプローラーには、作業の開始に役立つ一連のサンプル クエリが用意されています。

新しい API をアプリケーションに統合する前に、それらを試してみてください。

認証

Microsoft Graph を介してデータにアクセスするには、アプリケーションで OAuth 2.0 アクセス トークンを取得し、次のいずれかのオプションで Microsoft Graph に提示する必要があります。

  • HTTP Authorization 要求ヘッダー (Bearer トークンとして)
  • グラフ クライアント コンストラクター (Microsoft Graph クライアント ライブラリを使用する場合)

Microsoft 認証ライブラリ (MSAL) を使用して、Microsoft Graph へのアクセス トークンを取得します。

アプリで同意と承認を行うには、次のベスト プラクティスを適用します。

  • 最小限の特権を適用する。 ユーザーとアプリに、API の呼び出しに必要な最も低い特権のアクセス許可のみを付与します。 メソッドに関するトピックの「アクセス許可」セクションを確認し (例として「ユーザーを作成する」をご覧ください)、必要最小限の権限が付与されたアクセス許可を選択します。 たとえば、アプリが現在サインインしているユーザーのプロファイルのみを読み取る場合は、User.ReadBasic.All の代わりに User.Read を付与します。 アプリがユーザーの予定表を読み取らない場合は、 Calendars.Read アクセス許可を付与しないでください。 アクセス許可の完全な一覧については、「アクセス許可のリファレンス」をご覧ください。

  • シナリオに応じて適切なアクセス許可の種類を使用する。 同じアプリでアプリケーションと委任されたアクセス許可の両方を使用しないようにします。 サインインしているユーザーが存在している対話型のアプリケーションを作成する場合、そのアプリケーションは委任されたアクセス許可を使用する必要があります。 ただし、バックグラウンド サービスまたはデーモンなど、サインインしているユーザーなしで動作するアプリケーションの場合は、アプリケーションのアクセス許可を使用する必要があります。

    注意

    アプリケーションのアクセス許可を対話型のシナリオで使用すると、アプリケーションがコンプライアンスやセキュリティ上のリスクにさらされる恐れがあります。 これにより、ユーザーの権限を誤って昇格させ、管理者によって設定されたポリシーを回避してデータにアクセスできるようにしてしまう可能性があります。

  • 慎重にアプリを構成する。 これは、エンドユーザーや管理者のエクスペリエンス、およびアプリケーションの導入とセキュリティに直接影響します。 例:

    • アプリケーションの名前、ロゴ、ドメイン、発行元の検証状態、プライバシーに関する声明、使用条件は、同意やその他のエクスペリエンスに表示されます。 エンド ユーザーが認識できるように、これらの設定を慎重に構成します。
    • アプリケーションに同意するのがどのようなユーザーなのか (エンドユーザーか管理者か) を考慮した上で、アプリケーションが適切なアクセス許可を要求するように構成します。
    • 静的、動的、増分同意の違いを確実に理解している必要があります。
  • マルチテナント アプリケーションを考慮する。 ユーザーによって、アプリケーションや同意のコントロールはまちまちで、その状態もさまざまであることを想定します。 例:

    • テナント管理者は、エンドユーザーがアプリケーションに同意する機能を無効にできます。 この例では、管理者がユーザーに代わって同意する必要があります。
    • テナント管理者は、ユーザーが他のユーザーのプロファイルを読み取れないようにする場合や、セルフ サービスのグループ作成を限られたユーザーのみに限定する場合のように、カスタム承認ポリシーを設定できます。 この例では、アプリケーションがあるユーザーの代理として動作している場合、そのアプリケーションが 403 Forbidden エラー応答を処理することを想定する必要があります。

応答を効果的に処理する

Microsoft Graph に対して行う要求に応じて、アプリケーションがさまざまな種類の応答を処理できるようにしておく必要があります。 エンドユーザーがアプリケーションの動作を信頼し予測できるようにするために従う必要のある、最も重要なプラクティスの一部を次に示します。

改ページ

リソース コレクションのクエリを実行する場合、Microsoft Graph が返す結果セットは、サーバー側のページ サイズ制限が原因で複数ページになることを想定する必要があります。 要求セットが複数ページにまたがる場合、Microsoft Graph は、結果の次ページへの URL を格納する @odata.nextLink プロパティを応答で返します。

たとえば、サインインしているユーザーを一覧表示する次のようなメッセージの場合、

GET https://graph.microsoft.com/v1.0/me/messages

結果セットがサーバー側のページ サイズ制限を超えると、@odata.nextLink プロパティを格納した応答が返されます。

"@odata.nextLink": "https://graph.microsoft.com/v1.0/me/messages?$skip=23"

注:

作成するアプリケーションは、応答が実際にページングされている可能性を常に考慮し、結果の次ページのセットを取得する @odata.nextLink プロパティを使用して、結果セットのページを最後まですべて読み取るようにする必要があります。 最後のページには、@odata.nextLink プロパティが含まれません。 結果の次ページを要求する際は、その URL 全体を符号化文字列として処理して @odata.nextLink プロパティに格納する必要があります。

詳細については、「 ページング」を参照してください。

予想されるエラーの処理

アプリケーションはすべてのエラー応答 (400 および 500 の範囲) を処理する必要がありますが、次の表に示す、予想される特定のエラーと応答に特に注意を払う必要があります。

トピック HTTP エラー コード ベスト プラクティス
ユーザーにアクセス権がありません 403 アプリケーションが起動して実行している場合、同意エクスペリエンスで必要なアクセス許可を与えられていても、このエラーが発生することがあります。 この場合、サインインしているユーザーに要求されたリソースにアクセスする権限がない可能性が最も高くなります。 アプリケーションは、サインインしているそのユーザーに、汎用の「アクセスが拒否されました」というエラーを返す必要があります。
見つかりません 404 場合によっては、要求されたリソースが検出できないことがあります。 たとえば、リソースがまだプロビジョニングされていない (ユーザーの写真など) か、削除されているため、リソースが存在しない可能性があります。 削除された一部のリソース (ユーザー、グループ、アプリケーション リソースなど) は、削除から 30 日以内であれば完全に復元される可能性があるため、アプリケーションはこの点も考慮に入れる必要があります。
スロットル 429 API はさまざまな理由でいつでも調整される可能性があるため、アプリケーションは 常に 429 の応答を処理するように準備する必要があります。 このエラー応答には、Retry-After フィールドが HTTP 応答ヘッダーに格納されています。 Retry-After の延期期間を使用して要求を一旦取り消すことが、最も迅速にスロットルを解消する方法です。 詳細については、「スロットル」をご覧ください。
サービスを使用できません 503 これは、サービスがビジー状態になっている可能性があります。 429 と同様に、要求を一旦取り消す方法を採用する必要があります。 さらに、新しい HTTP 接続経由で再試行要求を新たに作成することが常に必要です。

進化可能な列挙型で将来のメンバーを処理する

既存の列挙型にメンバーを追加すると、これらの列挙型をすでに使用しているアプリケーションが破損する可能性があります。 進化可能な列挙型は、アプリケーションに重大な変更を加えることなく、既存の列挙型に新しいメンバーを追加するためにMicrosoft Graph API が使用するメカニズムです。

進化可能な列挙型には、最初に列挙型で定義された既知のメンバーと、後で追加される、または将来定義される未知のメンバーを区切る、unknownFutureValue と呼ばれる共通のセンチネル メンバーがあります。 内部的には、既知のメンバーはセンチネル メンバーよりも小さい数値にマップされ、未知のメンバーはセンチネル メンバーよりも大きくなります。 進化可能な列挙型のドキュメントには、可能な文字列値が昇順でリストされています。既知のメンバー、次に、unknownFutureValue、不明のメンバーが続きます。 他の種類の列挙型と同様に、進化可能な列挙型のメンバーは常に文字列値で参照する必要があります。

既定では、GET 操作は、進化可能な列挙型のプロパティの既知のメンバーのみを返し、アプリケーションは既知のメンバーのみを処理する必要があります。 不明なメンバーを処理するようにアプリケーションを設計する場合は、HTTP Prefer 要求ヘッダーを使用してそれらのメンバーを受信することを選択できます。

Prefer: include-unknown-enum-members

ローカルにデータを保存する

アプリケーションは、Microsoft Graph に対して呼び出しを実行し、必要に応じてリアルタイムでデータを取得するのが理想的です。 特定のシナリオに必要な場合に限って、データをローカルにキャッシュし保存するようにします。そのようなユース ケースが使用条件やプライバシー ポリシーの対象となっている場合は、「Microsoft API の利用規約」に違反しないようにする必要があります。 適切な保持ポリシーと削除ポリシーをアプリケーションに実装する必要もあります。

最適化

一般に、パフォーマンス、セキュリティ、プライバシー保護などの理由から、アプリケーションが本当に必要とするデータのみを取得するようにする必要があります。

使用予測

アプリケーションで本当に必要となるプロパティのみを選択します。これにより、不要なネットワーク トラフィックだけでなく、アプリケーション (やサービス) での不要なデータ処理を削減できます。

注:

クエリから返されるプロパティをアプリケーションで必要なものだけに制限するには、$select クエリ パラメーターを使用します。

たとえば、サインイン ユーザーのメッセージを取得するとき、from プロパティと subject プロパティだけを返すよう指定できます。

GET https://graph.microsoft.com/v1.0/me/messages?$select=from,subject

$selectを使用してプロパティ データの量を制限せずに GET 要求を行う場合、Microsoft Graph には、次のような$selectを使用するためのベスト プラクティスの推奨事項を提供する @microsoft.graph.tips プロパティが含まれています。

"@microsoft.graph.tips": "Use $select to choose only the properties your app needs, as this can lead to performance improvements. For example: GET groups?$select=appMetadata,assignedLabels",

最低限の応答を取得する

PUT、PATCH (および一部の POST) などのいくつかの操作では、アプリケーションで応答ペイロードを利用する必要がない場合、API が最低限のデータを返すようにできます。 一部のサービスでは、PUT 操作と PATCH 操作に対して 204 No Content 応答が既に返されています。

注:

Prefer ヘッダーを return=minimal に設定して最小限の表現応答を要求します (サポートされている場合)。 作成操作では、アプリケーションが応答で新しく作成されたオブジェクトの id で生成されたサービスを取得することを想定している可能性があるため、このヘッダーを使用するのが適切でない場合があります。

変更履歴の記録: デルタ クエリと webhook 通知

アプリケーションでデータへの変更を認識する必要がある場合、対象データが変更されるたびに webhook 通知を取得できます。 これは、単に定期的にポーリングするよりも効率的です。

データが変更されたときにプッシュ通知を取得するには、webhook 通知を使用します。

アプリケーションで Microsoft Graph データをローカルにキャッシュまたは保存し、そのデータを常に最新の状態に保ったり、何らかの理由でデータへの変更履歴を記録したりする必要がある場合は、デルタ クエリを使用する必要があります。 これにより、アプリケーションが既に持っているデータを取得し、ネットワーク トラフィックを最小限に抑え、調整しきい値に達する可能性を減らすために、アプリケーションによる過剰な計算が回避されます。

効率よくデータを最新の状態に保つには、デルタ クエリを使用します。

webhook とデルタ クエリを組み合わせて使用する

Webhook とデルタ クエリは、一緒に使用されることが多いため、デルタ クエリだけを使用する場合は、適切なポーリング間隔を把握する必要があるためです。短すぎると、空の応答が発生する可能性があるため、リソースが浪費され、古いデータが発生する可能性があります。 webhook 通知をデルタ クエリ呼び出しを実行するトリガーとして使うと、最適な結果が得られます。

webhook 通知を、デルタ クエリ呼び出しを実行するトリガーとして使用します。 通知がトリガーされない場合に備えて、バックストップ ポーリングしきい値をアプリケーションに指定しておく必要もあります。

バッチ処理

JSON のバッチ処理を使用すると、複数の要求を単一の JSON オブジェクトに統合することにより、アプリケーションを最適化することができます。 それぞれの要求を 1 つのバッチ要求にまとめることで、アプリケーションのネットワーク待機時間を大きく削減し、接続リソースを節約することができます。

大量のネットワーク待機時間がパフォーマンスに大きな影響を与える可能性がある バッチ処理 を使用します。

信頼性とサポート

アプリケーションの信頼性を確保しサポートを容易にするには、次のようにします。

  • TLS 1.3 または 1.2 を使用して、Microsoft Graph のすべての機能をサポートします。 TLS 1.0 および 1.1 から移行します。 詳細については、「 環境内で TLS 1.2 のサポートを有効にする」を参照してください。
  • DNS TTL を優先し、接続 TTL をそれに合わせて設定します。 これにより、フェールオーバーの際の可用性を確保できます。
  • アドバタイズされたすべての DNS 応答に対して接続を開きます。
  • 一意の GUID を生成し、Microsoft Graph Rest 要求ごとに送信します。 これにより、Microsoft Graph に関する問題を報告する必要がある場合に、エラーをより簡単に調査できます。
    • Microsoft Graph への要求ごとに一意の GUID が生成され、その GUID は client-request-id HTTP 要求ヘッダー内に送信され、アプリケーションのログにも記録されます。
    • HTTP 応答ヘッダーから常に request-idDate をログに記録します。 これらは、client-request-id と共に、Microsoft Q&A または Microsoft サポートに問題を報告する際に必要です。