💻
Microsoft Graph で会議室の予定表を取得する
元ネタはこちらです。
OAuth を使ったアプリケーションで「アクセス許可を与えたのにデータが取れない」という状況が発生するということをよく耳にします。
上記の「Calendars.ReadWrite.Shared
を付けたのに会議室の情報が取れない」というのは、アプリを使用するユーザーに権限がないからです。これはむしろ正しい動作といえます。委任されたアクセス許可 という名前が表す通りですね。
Microsoft のドキュメントにも説明があります。
委任されたアクセス許可の場合、アプリの有効なアクセス許可は、アプリに付与されている委任されたアクセス許可 (同意によって付与) と現在サインインしているユーザーの特権が重なる範囲に収まる最小権限になります。
対応方法としては アプリケーションのアクセス許可 を使うことになります。ただし、こちらは、バックグラウンドで動作するアプリケーションを想定しているので、気を付けなければなりません。たとえば、アクセス許可に 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