Microsoft Graph を使用してユーザーの予定表イベントにアクセスする

完了

ASP.NET Core アプリを実行し、Microsoft 365 に接続しました。 このユニットでは、ユーザーの翌週の予定表イベントを表示する方法について説明します。 また、指定した期間のデータ イベントのクエリを実行する方法についても学びます。 最後に、selectorder などの概念を学び、希望する方法で情報を表示します。

アプリに必要なアクセス許可を決定する

Microsoft Graph によって公開されるすべてのデータは、セキュリティで保護されているため、アプリがアクセスするために適切なアクセス許可が必要です。 必要なアクセス許可は、アプリがアクセスする必要のある情報の種類によって異なります。 たとえば、ユーザーの予定表にアクセスするには、アプリに Calendars.Read アクセス許可が付与される必要があります。 各操作に必要なアクセス許可の正確な一覧は、Microsoft Graph API リファレンスで確認できます。

アプリがさまざまな種類のデータを読み込む場合、ユーザーは、この情報へのアクセスに必要な複数のアクセス許可を付与する必要があります。 必要なアクセス許可のみをアプリ内で要求することをお勧めします。

必要なアクセス許可を指定する

アプリに付与されているアクセス許可のリストはアクセス トークンに直接組み込まれます。 OAuth 標準でこれは “スコープ" と呼ばれています。 アプリケーションで MSAL を使用してアクセス トークンを取得する場合は、Microsoft Entra ID への要求にスコープの一覧を含める必要があります。  Microsoft Graph の各操作には、独自のスコープの一覧があります。 アクセス トークンにこれらのスコープが 1 つも存在しない場合、要求は拒否されます。

サンプル アプリケーションでは、前に見たように appsettings.json ファイルの Scopes プロパティに必要なアクセス許可を格納しています。

"Scopes": "user.read presence.read mailboxsettings.read calendars.read"

Scopes プロパティの値は、アプリの ASP.NET Core ミドルウェアで使用され、ユーザーがサインインに成功した後にアクセス トークンを取得する処理を行います。

ミドルウェア: Microsoft ID プラットフォームと Microsoft Graph

ASP.NET Core は、ユーザーの認証や認可に使用できるミドルウェアをサポートします。 また、Microsoft Graph の呼び出しに使用できるトークンの取得、GraphServiceClient という Microsoft Graph SDK オブジェクトのアプリケーションへの取り込み、トークン キャッシュの作成などにも使用できます。 ミドルウェアは Startup.cs で設定し、以下のタスクを処理します。

  1. Scopes プロパティで定義された必要なアクセス許可を appsettings.json で取得します。
  2. OpenId 認証のサポートを追加します。
  3. アプリケーションが、認証コード フローを必要とする Microsoft ID プラットフォームの Web アプリであることを指定します。
  4. 特定のアクセス許可を持つ Microsoft Graph API を呼び出す機能を追加します。
  5. GraphServiceClient 用の依存関係の取り込み (Microsoft Graph SDK が提供するオブジェクトで、Microsoft Graph の呼び出しに使用されます) を有効にします。
  6. メモリ内トークン キャッシュを追加します。
  7. アプリへのアクセスには、認証されたユーザーが必要です。
  8. Razor Pages のサポートを有効にします。
  9. ユーザーのサインインおよびサインアウトをサポートする Microsoft ID UI ページを追加します。

これらの各手順は、Startup.csConfigureServices() メソッドで定義された以下のコードで確認できます。

// 1. Retrieve required permissions from appsettings
string[] initialScopes =
Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');


services
  // 2. Add support for OpenId authentication
  .AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)

  // 3. Microsoft identity platform web app that requires an auth code flow
  .AddMicrosoftIdentityWebApp(Configuration)

  // 4. Add ability to call Microsoft Graph APIs with specific permissions
  .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)

  // 5. Enable dependency injection for GraphServiceClient
  .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))

  // 6. Add in-memory token cache
  .AddInMemoryTokenCaches();


// 7. Require an authenticated user
services.AddControllersWithViews(options =>
{
  var policy = new AuthorizationPolicyBuilder()
      .RequireAuthenticatedUser()
      .Build();
  options.Filters.Add(new AuthorizeFilter(policy));
});

services
  // 8. Add Razor Pages support
  .AddRazorPages()

  // 9. Add Microsoft Identity UI pages that provide user
  // sign-in and sign-out support
  .AddMicrosoftIdentityUI();

必要なミドルウェアが構成されると、アプリケーションは自動的にユーザーのサインインとアクセス トークンの取得を処理します。 アクセス トークンには、必要なアクセス許可が含まれるため、ユーザーのカレンダー イベントを取得するのに使用することができます。 そのプロセスのしくみを見てみましょう。

一定の期間内におけるユーザーの予定表イベントを取得する

ユーザーの予定表イベントを Microsoft Graph から取得する場合、/me/calendarview エンドポイントを呼び出す必要があります。 サインインしているユーザーの既定の予定表から、カレンダー イベントのリストを返します。 Microsoft Graph への呼び出しは、先ほどミドルウェアの項で紹介した GraphServiceClient オブジェクトを使用して行うことができます。 GraphServiceClient には、HTTP 呼び出しを手動で行うことなく Microsoft Graph を呼び出すために使用できる API があります。 次の週のカレンダー イベントを表示するには、週の開始日と終了日を定義する必要があります。

// Configure a calendar view for the current week
var startOfWeek = DateTime.Now;
var endOfWeek = startOfWeek.AddDays(7);

これらの日付は、選択するイベントの範囲を定義する QueryOption リストに追加されます。

var viewOptions = new List<QueryOption>
{
  new QueryOption("startDateTime", startOfWeek.ToString("o")),
  new QueryOption("endDateTime", endOfWeek.ToString("o"))
};

次に、GraphServiceClient オブジェクト (Razor ページのモデル クラスのコンストラクターに挿入) を使用して Me.CalendarView を呼び出し、viewOptions リストを Request メソッドに渡して結果を制限します。 このコードでは、Header メソッドを呼び出すことで、ユーザーの優先タイムゾーンも含まれます。

// Use the injected GraphServiceClient object to call into Me.CalendarView
var calendarEvents = await _graphServiceClient
    .Me
    .CalendarView
    .Request(viewOptions)
    .Header("Prefer", $"outlook.timezone=\"{userTimeZone}\"")

Microsoft Graph が取得および転送するデータの量を最小限に抑えると、アプリのパフォーマンスが大幅に向上します。 GraphServiceClient’s select メソッドは、アプリが使用する特定のプロパティを選択するために使用できます。

.Select(evt => new
{
    evt.Subject,
    evt.Organizer,
    evt.Start,
    evt.End
})

最後に、OrderBy メソッドで結果の項目の並べ替え方法を指定し、GetAsync を呼び出して要求を開始します。

.OrderBy("start/DateTime")
.GetAsync();

この場合、コードは start プロパティのサブプロパティである DateTime で結果を並べ替えます。 複数のフィールドによって並べ替える場合は、フィールドのコンマ区切りのリストを指定します。 asc またはdesc のキーワードをクエリに追加することによって、アイテムを昇順または降順に並べ替えることもできます。 コードの完全なバージョンを次に示します。

// Configure a calendar view for the current week
var startOfWeek = DateTime.Now;
var endOfWeek = startOfWeek.AddDays(7);

var viewOptions = new List<QueryOption>
{
    new QueryOption("startDateTime", startOfWeek.ToString("o")),
    new QueryOption("endDateTime", endOfWeek.ToString("o"))
};

// Use the injected GraphServiceClient object to call into Me.CalendarView
var calendarEvents = await _graphServiceClient
    .Me
    .CalendarView
    .Request(viewOptions)
    .Header("Prefer", $"outlook.timezone=\"{userTimeZone}\"")
    .Select(evt => new
    {
        evt.Subject,
        evt.Organizer,
        evt.Start,
        evt.End
    })
    .OrderBy("start/DateTime")
    .GetAsync();

このコードをアプリケーションで使用する方法を検討してみましょう。