💻

Microsoft Graph で会議室の予定表を取得する

に公開

元ネタはこちらです。

https://social.msdn.microsoft.com/Forums/ja-JP/2c124c80-585b-426f-94ed-68131049e954?WT.mc_id=M365-MVP-5002941

OAuth を使ったアプリケーションで アクセス許可を与えたのにデータが取れない という状況になることがあります。

上記の Calendars.ReadWrite.Shared を付けたのに会議室の情報が取れない というのは、アプリを使用するユーザーに権限がないためです。これは、委任されたアクセス許可という名前が示す通りの動作です。

Microsoft のドキュメントにも説明があります。

https://developer.microsoft.com/ja-jp/graph/docs/concepts/permissions_reference?WT.mc_id=M365-MVP-5002941

委任されたアクセス許可の場合、アプリの有効なアクセス許可は、アプリに付与されている委任されたアクセス許可 (同意によって付与) と現在サインインしているユーザーの特権が重なる範囲に収まる最小権限になります。

対応方法としては、アプリケーションのアクセス許可を使用します。ただし、こちらはバックグラウンドで動作するアプリケーションを想定しているため、注意が必要です。たとえば、アクセス許可に Calendars.Read を付与すると、特定のアカウントだけでなく、すべてのアカウントの予定表が参照可能になります。これはセキュリティ上のリスクが高くなるため、フロントエンドで動作するアプリでの利用は特に注意してください。

ここからはサンプルコードです。今回は MSAL を使用しています。

using Microsoft.Identity.Client;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace ConsoleApplication1
{

    public static class Program
    {

        private static readonly string TenantId = "{{tenant-id}}";
        private static readonly string RedirectUrl = "{{redirect-url}}";
        private static readonly string ClientId = "{{client-id}}";
        private static readonly string ClientSecret = "{{client-secret}}";

        private static readonly string Authority = $"https://login.microsoftonline.com/{TenantId}/v2.0";
        private static readonly string ResourceId = "https://graph.microsoft.com/.default";
        private static readonly string RequestUrl = "https://graph.microsoft.com/v1.0/users/{0}/calendarView?StartDateTime={1:s}&EndDateTime={2:s}";

        private static void Main(string[] args)
        {
            var userId = "{{resource-id}}";
            var startDateTime = DateTime.Today;
            var endDateTime = DateTime.Today.AddDays(1);
            GetCalendarAsync(userId, startDateTime, endDateTime).GetAwaiter().GetResult();
        }

        private static async Task GetCalendarAsync(string userId, DateTime startDateTime, DateTime endDateTime)
        {
            var oauthClient = new ConfidentialClientApplication(ClientId, Authority, RedirectUrl, new ClientCredential(ClientSecret), null, new TokenCache());
            var oauthResult = await oauthClient.AcquireTokenForClientAsync(new[] { ResourceId });
            var httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", oauthResult.AccessToken);
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var responseMessage = await httpClient.GetAsync(string.Format(RequestUrl, userId, startDateTime, endDateTime));
            var responseContent = await responseMessage.Content.ReadAsStringAsync();
        }

    }

}

なお、findMeetingTimes はアプリケーションのアクセス許可では動作しません。この機能を利用したい場合は、メールボックスにアクセス許可を付与する必要があります。

Discussion