Microsoft Graph. Подключение к данным
Первый пост из серии, посвященной работе с Microsoft Graph. В первой части о том, как подключаться к Microsoft Graph из приложений, написанных на .Net.
Создание приложения в Azure
Первое, что необходимо сделать - создать новое приложение в Azure Portal (manage.windowsazure.com).
Для этого переходим к списку приложений (Active Directory, выбираем домен и на закладку Applications) и нажимаем Add:
Приложение будет кастомное, поэтому в диалоговом окне выбираем соответственно 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. Обратиться за токеном может как приложение, так и пользователь (в случае, когда приложение работает в контексте безопасности конкретного пользователя).
Токен для приложения
Приложение получает токен, передавая три параметра:
- Ресурс,к которому необходим доступ
- Client ID
- Secret Key
Последние два доступны из раздела конфигурации приложения.
Токен для пользователя
В случае с пользователем получение токена несколько сложнее, требуется указывать дополнительный параметр - code:
- Ресурс,к которому необходим доступ
- Client ID
- Secret Key
- 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:
- namespace Microsoft.Graph
- {
- public interface IAuthenticationProvider
- {
- Task AuthenticateRequestAsync(HttpRequestMessage request);
- }
- }
Задача этого метода заключается в записи токена в заголовок сообщения. Примерная реализация провайдера для Service-to-Service авторизации:
- public class DemoAppAuthenticationProvider : IAuthenticationProvider
- {
- public async Task AuthenticateRequestAsync(HttpRequestMessage request)
- {
- // CLIENT ID из конфигурации приложения в Azure Portal
- var clientId = @"27015206-d28a-45a6-a952-a1e987edf216";
-
- // SECRET KEY из конфигурации приложения в Azure Portal
- var clientKey = @"==SECRETKEY==";
-
- // Домен Azure
- var azureDomain = @"vitalyzhukov.onmicrosoft.com";
-
- // URL для формирования контекста аутентификации
- var authory = $@"https://login.windows.net/{azureDomain}/oauth2/token";
-
- // Ресурс, доступ к которому необходимо получить
- var resourse = @"https://graph.microsoft.com/";
-
- // Учетные данные приложения
- var creds = new ClientCredential(clientId, clientKey);
-
- // Контекст аутентификации
- var authContext = new AuthenticationContext(authory);
-
- // Запрашиваем токен
- var authResult = await authContext.AcquireTokenAsync(resourse, creds);
-
- // Добавляем полученный токен в заголовок сообщения
- request.Headers.Add("Authorization", "Bearer " + authResult.AccessToken);
- }
- }
GraphServiceClient
Microsft Graph Client Library содержит класс для доступа к данным - Microsoft.Graph.GraphServiceClient, конструктор которого принимает экземпляр класс, реализующего интерфейс IAuthenticationProvider. Как раз такой описан абзацем выше. Вот некоторые классы Microsft Graph Client Library:
Консольное приложение будет делать следующее: выбирать первые 100 пользователей, фамилия которых начинается с буквы Ж и выводить их имена. В виде кода реализация такой задачи выглядит примерно так:
- // Кастомный провайдер
- var provider = new DemoAppAuthenticationProvider();
- // Клиент для работы с Microsoft Graph
- var client = new GraphServiceClient(provider);
-
- // Отбираем первые 100 результатов
- var option = new QueryOption("$top", "100");
- // Фильтруем данные
- var filter = "(startswith(surname,'Ж'))";
-
- // Формируем запрос к Microsoft Graph
- var request = client
- .Users
- .Request(new[] { option})
- .Filter(filter);
-
- // Выводим получившийся Uri
- Console.WriteLine(request.GetHttpRequestMessage().RequestUri.ToString());
-
- // Ожидаем результата выполнения запроса
- var users = request
- .GetAsync()
- .GetAwaiter()
- .GetResult();
-
- // Выводим информацию о пользователях
- foreach (var user in users)
- {
- Console.WriteLine("DisplayName: \t" + user.DisplayName);
- }
И результат его работы в консоле:
В консоле я вывел итоговый URI, результаты которого можно проверить в Microsoft Graph Explorer:
Переходим в веб-приложению и авторизации пользователя.
ASP.NET приложение, отображающее данные из Microsoft Graph
Демонстрационное ASP.NET приложение будет содержать две страницы: default.aspx и me.aspx для авторизации и отображения информации о пользователе соответственно.
Редирект в Azure Login
На странице default.aspx расположена кнопка при нажатии на которую пользователь будет отправлен на страницу авторизации login.microsoftonline.com. Код следующий:
- protected void OnLoginButtonClick(object sender, EventArgs e)
- {
- // CLIENT ID из конфигурации приложения в Azure Portal
- var clientId = @"27015206-d28a-45a6-a952-a1e987edf216";
-
- // SECRET KEY из конфигурации приложения в Azure Portal
- var clientKey = @"==SECRETKEY==";
-
- // Домен Azure
- var azureDomain = @"vitalyzhukov.onmicrosoft.com";
-
- // URL для формирования контекста аутентификации
- var authory = $@"https://login.windows.net/{azureDomain}/oauth2/token";
-
- // Ресурс, доступ к которому необходимо получить
- var resourse = @"https://graph.microsoft.com/";
-
- // Контекст аутентификации
- var authContext = new AuthenticationContext(authory);
-
- // URL для перенаправления после авторизации
- var redirectUrl = new Uri("http://localhost:27327/Me.aspx");
-
- // Формируем URL для Azure login.
- var authUri = authContext.GetAuthorizationRequestURL(
- resourse,
- clientId,
- redirectUrl,
- UserIdentifier.AnyUser,
- null);
-
- Response.Redirect(authUri.ToString());
- }
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 Login будет выдано сообщение об ошибке:
После успешной авторизации к указанному redirect_uri будет добавлен параметр code
Чтение данных из Microsoft Graph
Для веб-приложения провайдер будет упрощен. Токен он сразу будет принимать при инициализации:
- public class DemoWebAuthenticationProvider : IAuthenticationProvider
- {
- public DemoWebAuthenticationProvider(string token)
- {
- Token = token;
- }
-
- public async Task AuthenticateRequestAsync(HttpRequestMessage request)
- {
- // Добавляем полученный токен в заголовок сообщения
- request.Headers.Add("Authorization", "Bearer " + Token);
- }
-
- public string Token;
- }
На странице me.aspx отобразим имя текущего пользователя и список папок почты. В коде это выглядит вот так:
- public partial class Me : Page
- {
- protected void Page_Load(object sender, EventArgs e)
- {
- // Код авторизации
- var code = Request.QueryString["code"];
-
- // Если код не указан
- if (string.IsNullOrEmpty(code))
- return;
-
- RegisterAsyncTask(new PageAsyncTask(async () =>
- {
- // CLIENT ID из конфигурации приложения в Azure Portal
- var clientId = @"27015206-d28a-45a6-a952-a1e987edf216";
-
- // SECRET KEY из конфигурации приложения в Azure Portal
- var clientKey = @"==SECRETKEY==";
-
- // URL для формирования контекста аутентификации
- var authory = @"https://login.microsoftonline.com/common";
-
- // URL для перенаправления после авторизации
- var redirectUrl = new Uri("http://localhost:27327/Me.aspx");
-
- // Учетные данные приложения
- var creds = new ClientCredential(clientId, clientKey);
-
- // Контекст аутентификации
- var authContext = new AuthenticationContext(authory);
-
- // Запрашиваем токен
- var authResult = authContext.AcquireTokenByAuthorizationCode(code, redirectUrl, creds);
-
- // GraphServiceClient
- var client = new GraphServiceClient(new DemoWebAuthenticationProvider(authResult.AccessToken));
-
- MeUser = await client.Me
- .Request()
- .GetAsync();
-
- MeMailFolders = (await client
- .Me.MailFolders
- .Request()
- .GetAsync())
- .ToList();
- }));
- }
-
- public List<MailFolder> MeMailFolders { get; set; }
-
- public Microsoft.Graph.User MeUser { get; set; }
- }
Разметка страницы:
И результат:
Исходные коды
Исходные коды приложений доступны в OneDrive.