Microsoft Graph. Подключение к данным

Первый пост из серии, посвященной работе с Microsoft Graph. В первой части о том, как подключаться к Microsoft Graph из приложений, написанных на .Net.

Создание приложения в Azure

Первое, что необходимо сделать - создать новое приложение в Azure Portal (manage.windowsazure.com).

Для этого переходим к списку приложений (Active Directory, выбираем домен и на закладку Applications) и нажимаем Add:

Приложения в Azure Portal

Приложение будет кастомное, поэтому в диалоговом окне выбираем соответственно Add an application my organization is developing:

Указываем имя приложения:

Дальше указываем любые Sign-On и App ID URI:

Приложение создано, переходим к разделу Configure:

Настройка приложения в Azure Portal

В разделе настройки приложения создаем новый секретный ключ и даем приложению права на использование Microsoft Graph.

От приложения нам на первом этапе понадобятся следующие значения:

  • CLIENT ID
  • SECRET KEY

Приложение в Azure для доступа к Microsoft Graph создано, теперь перейдем к созданию демонстрационных приложений, которые будут получать данные из API.

Сначала небольшое отступление про безопасность.

Безопасность в Azure AD при работе с API

Если совсем упрощать, то для доступа к API нам необходим некий токен, получить который возможно только в Azure AD. Обратиться за токеном может как приложение, так и пользователь (в случае, когда приложение работает в контексте безопасности конкретного пользователя).

Токен для приложения

Приложение получает токен, передавая три параметра:

  1. Ресурс,к которому необходим доступ
  2. Client ID
  3. Secret Key

Последние два доступны из раздела конфигурации приложения.

Токен для пользователя

В случае с пользователем получение токена несколько сложнее, требуется указывать дополнительный параметр - code:

  1. Ресурс,к которому необходим доступ
  2. Client ID
  3. Secret Key
  4. Code

Указанный код можно получить только после авторизации пользователем на странице login.microsoftonline.com. Таким образом приложение перенаправляет пользователя на страницу авторизации, а затем после авторизации Azure AD перенаправляет пользователя обратно с указанием этого самого кода.

Для демонстрации я опишу создание двух простых приложений: консольного, для доступа к данным в Microsoft Graph и авторизации как приложение (Service-to-Service) и ASP.NET-приложение с авторизацией пользователя.

Создаем приложение в Visual Studio

Сначала создадим простое консольное приложение, которое будет выводить информацию из Microsoft Graph. В Visual Studio создаем новое консольное приложение:

Для работы понадобятся Active Directory Authentication Library и Microsoft Graph Client Library. Устанавливаем их с помощью Package Manager Console:

Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory и Install-Package Microsoft.Graph

Ссылки в проекте после этого должны быть примерно следующими:

Провайдер для Microsoft Graph

Для использование клиентской библиотека Microsoft Graph и подключение к API Microsoft Graph необходимо реализовать интерфейс IAuthenticationProvider, который прост и содержит единственный метод AuthenticateRequestAsync:

  1. namespace Microsoft.Graph
  2. {
  3.     public interface IAuthenticationProvider
  4.     {
  5.         Task AuthenticateRequestAsync(HttpRequestMessage request);
  6.     }
  7. }

Задача этого метода заключается в записи токена в заголовок сообщения. Примерная реализация провайдера для Service-to-Service авторизации:

  1. public class DemoAppAuthenticationProvider : IAuthenticationProvider
  2. {
  3.     public async Task AuthenticateRequestAsync(HttpRequestMessage request)
  4.     {
  5.         // CLIENT ID из конфигурации приложения в Azure Portal
  6.         var clientId = @"27015206-d28a-45a6-a952-a1e987edf216";
  7.             
  8.         // SECRET KEY из конфигурации приложения в Azure Portal
  9.         var clientKey = @"==SECRETKEY==";
  10.             
  11.         // Домен Azure
  12.         var azureDomain = @"vitalyzhukov.onmicrosoft.com";
  13.             
  14.         // URL для формирования контекста аутентификации
  15.         var authory = $@"https://login.windows.net/{azureDomain}/oauth2/token";
  16.             
  17.         // Ресурс, доступ к которому необходимо получить
  18.         var resourse = @"https://graph.microsoft.com/";
  19.  
  20.         // Учетные данные приложения
  21.         var creds = new ClientCredential(clientId, clientKey);
  22.             
  23.         // Контекст аутентификации
  24.         var authContext = new AuthenticationContext(authory);
  25.             
  26.         // Запрашиваем токен
  27.         var authResult = await authContext.AcquireTokenAsync(resourse, creds);
  28.  
  29.         // Добавляем полученный токен в заголовок сообщения
  30.         request.Headers.Add("Authorization""Bearer " + authResult.AccessToken);
  31.     }
  32. }

GraphServiceClient

Microsft Graph Client Library содержит класс для доступа к данным - Microsoft.Graph.GraphServiceClient, конструктор которого принимает экземпляр класс, реализующего интерфейс IAuthenticationProvider. Как раз такой описан абзацем выше. Вот некоторые классы Microsft Graph Client Library:

Microsoft.Graph.GraphServiceClient

Консольное приложение будет делать следующее: выбирать первые 100 пользователей, фамилия которых начинается с буквы Ж и выводить их имена. В виде кода реализация такой задачи выглядит примерно так:

  1. // Кастомный провайдер
  2. var provider = new DemoAppAuthenticationProvider();
  3. // Клиент для работы с Microsoft Graph
  4. var client = new GraphServiceClient(provider);
  5.  
  6. // Отбираем первые 100 результатов
  7. var option = new QueryOption("$top""100");
  8. // Фильтруем данные
  9. var filter = "(startswith(surname,'Ж'))";
  10.  
  11. // Формируем запрос к Microsoft Graph
  12. var request = client
  13.     .Users
  14.     .Request(new[] { option})
  15.     .Filter(filter);
  16.  
  17. // Выводим получившийся Uri
  18. Console.WriteLine(request.GetHttpRequestMessage().RequestUri.ToString());
  19.  
  20. // Ожидаем результата выполнения запроса
  21. var users = request
  22.     .GetAsync()
  23.     .GetAwaiter()
  24.     .GetResult();
  25.  
  26. // Выводим информацию о пользователях
  27. foreach (var user in users)
  28. {
  29.     Console.WriteLine("DisplayName: \t" + user.DisplayName);
  30. }

И результат его работы в консоле:

Microsoft Graph Console App

В консоле я вывел итоговый URI, результаты которого можно проверить в Microsoft Graph Explorer:

Microsoft Graph Explorer

Переходим в веб-приложению и авторизации пользователя.

ASP.NET приложение, отображающее данные из Microsoft Graph

Демонстрационное ASP.NET приложение будет содержать две страницы: default.aspx и me.aspx для авторизации и отображения информации о пользователе соответственно.

Редирект в Azure Login

На странице default.aspx расположена кнопка при нажатии на которую пользователь будет отправлен на страницу авторизации login.microsoftonline.com. Код следующий:

  1. protected void OnLoginButtonClick(object sender, EventArgs e)
  2. {
  3.     // CLIENT ID из конфигурации приложения в Azure Portal
  4.     var clientId = @"27015206-d28a-45a6-a952-a1e987edf216";
  5.  
  6.     // SECRET KEY из конфигурации приложения в Azure Portal
  7.     var clientKey = @"==SECRETKEY==";
  8.  
  9.     // Домен Azure
  10.     var azureDomain = @"vitalyzhukov.onmicrosoft.com";
  11.  
  12.     // URL для формирования контекста аутентификации
  13.     var authory = $@"https://login.windows.net/{azureDomain}/oauth2/token";
  14.  
  15.     // Ресурс, доступ к которому необходимо получить
  16.     var resourse = @"https://graph.microsoft.com/";
  17.  
  18.     // Контекст аутентификации
  19.     var authContext = new AuthenticationContext(authory);
  20.  
  21.     // URL для перенаправления после авторизации
  22.     var redirectUrl = new Uri("http://localhost:27327/Me.aspx");
  23.  
  24.     // Формируем URL для Azure login.
  25.     var authUri = authContext.GetAuthorizationRequestURL(
  26.         resourse,
  27.         clientId,
  28.         redirectUrl,
  29.         UserIdentifier.AnyUser,
  30.         null);
  31.  
  32.     Response.Redirect(authUri.ToString());
  33. }

URL-адрес, куда перенаправляется пользователь в моем случае вот такой:

https://login.microsoftonline.com/vitalyzhukov.onmicrosoft.com/oauth2/authorize
?resource=https:%2F%2Fgraph.microsoft.com%2F
&client_id=27015206-d28a-45a6-a952-a1e987edf216
&response_type=code
&haschrome=1
&redirect_uri=http:%2F%2Flocalhost:27327%2FMe.aspx
&x-client-SKU=.NET
&x-client-Ver=2.25.0.0
&x-client-CPU=x64
&x-client-OS=Microsoft+Windows+NT+10.0.10586.0

redirect_uri - куда пользователь будет перенаправлен после авторизации. Ровно этот URL должен быть указан в настройках приложения в Azure Portal:

Azure App Reply URI

В противном случае на странице Azure Login будет выдано сообщение об ошибке:

AADSTS50011: The reply address 'http://localhost:27327/Me.aspx' does not match the reply addresses configured for the application

После успешной авторизации к указанному redirect_uri будет добавлен параметр code

Чтение данных из Microsoft Graph

Для веб-приложения провайдер будет упрощен. Токен он сразу будет принимать при инициализации:

  1. public class DemoWebAuthenticationProvider : IAuthenticationProvider
  2. {
  3.     public DemoWebAuthenticationProvider(string token)
  4.     {
  5.         Token = token;
  6.     }
  7.  
  8.     public async Task AuthenticateRequestAsync(HttpRequestMessage request)
  9.     {
  10.         // Добавляем полученный токен в заголовок сообщения
  11.         request.Headers.Add("Authorization""Bearer " + Token);
  12.     }
  13.  
  14.     public string Token;
  15. }

На странице me.aspx отобразим имя текущего пользователя и список папок почты. В коде это выглядит вот так:

  1. public partial class Me : Page
  2. {
  3.     protected void Page_Load(object sender, EventArgs e)
  4.     {
  5.         // Код авторизации
  6.         var code = Request.QueryString["code"];
  7.  
  8.         // Если код не указан
  9.         if (string.IsNullOrEmpty(code))
  10.             return;
  11.  
  12.         RegisterAsyncTask(new PageAsyncTask(async () =>
  13.         {
  14.             // CLIENT ID из конфигурации приложения в Azure Portal
  15.             var clientId = @"27015206-d28a-45a6-a952-a1e987edf216";
  16.  
  17.             // SECRET KEY из конфигурации приложения в Azure Portal
  18.             var clientKey = @"==SECRETKEY==";
  19.  
  20.             // URL для формирования контекста аутентификации
  21.             var authory = @"https://login.microsoftonline.com/common";
  22.  
  23.             // URL для перенаправления после авторизации
  24.             var redirectUrl = new Uri("http://localhost:27327/Me.aspx");
  25.  
  26.             // Учетные данные приложения
  27.             var creds = new ClientCredential(clientId, clientKey);
  28.  
  29.             // Контекст аутентификации
  30.             var authContext = new AuthenticationContext(authory);
  31.  
  32.             // Запрашиваем токен
  33.             var authResult = authContext.AcquireTokenByAuthorizationCode(code, redirectUrl, creds);
  34.  
  35.             // GraphServiceClient
  36.             var client = new GraphServiceClient(new DemoWebAuthenticationProvider(authResult.AccessToken));
  37.  
  38.             MeUser = await client.Me
  39.                 .Request()
  40.                 .GetAsync();
  41.  
  42.             MeMailFolders = (await client
  43.                 .Me.MailFolders
  44.                 .Request()
  45.                 .GetAsync())
  46.                 .ToList();
  47.         }));
  48.     }
  49.  
  50.     public List<MailFolder> MeMailFolders { getset; }
  51.  
  52.     public Microsoft.Graph.User MeUser { getset; }
  53. }

Разметка страницы:

И результат:

Исходные коды

Исходные коды приложений доступны в OneDrive.

Смотрите также

Authorization Code Grant Flow

Service to Service Calls Using Client Credentials

Виталий Жуков

Виталий Жуков

Техлид, Архитектор, Разработчик, Microsoft MVP. Более 20 лет опыта в области системной интеграции и разработки программного обеспечения. Специализируюсь на проектировании и внедрении масштабируемых высокопроизводительных программных решений в различных отраслях.

Смотрите также

Microsoft Graph. Доступ к данным в SharePoint Online

Microsoft Graph. Доступ к данным в SharePoint Online

Создаем приложение для OneDrive с помощью AngularJS и Microsoft API

Создаем приложение для OneDrive с помощью AngularJS и Microsoft API

Презентация с доклада о Microsoft API и Office Graph

Презентация с доклада о Microsoft API и Office Graph