Office 365. Пример работы с Microsoft Graph API в Angular5 с помощью ADAL JS. ADAL JS vs MSAL JS
В прошлый раз мы обсудили механизм авторизации для работы с Office 365 API (в частности с Microsoft Graph API):
- при каждом вызове API нужно передать token. Token имеет ограниченный срок жизни
- token выдает сервис Microsoft, так называемый “Azure AD Authorization Endpoint”
- получить token можно без серверной части используя только JavaScript в браузере. Для этого Microsoft сделал JavaScript библиотеку ADAL JS, которая упрощает коммуникацию с “Azure AD Authorization Endpoint” для получения token.
Тогда мы сделали простую статичную HTML-страницу, на которой наш vanilla JavaScript делал запрос к Microsoft Graph API и отображал список писем из Office 365. В данной заметке разовьем пример и сделаем тоже самое на Angular5.
Также поговорим о различиях рабочих (Work or school account) и персональных (Personal Account) аккаунтов при использовании Office 365 API.
Пример на GitHab.
Будем считать, что вы знакомы с предыдущей статьёй, понимаете процесс получения и использования token, уже зарегистрировали приложение в Azure, получили Application ID.
ADAL JS и MSAL JS
У Microsoft есть два вида аккаунтов:
— Work or school Account
— Personal Account
Work or school account создается (и удаляется) администратором компании, которая купила подписку Office 365. Сотрудники используют его, например, для подключения к корпоративной почте, SharePoint, OneDrive.
Personal Account создаете вы сами, используется для подключения к персональным сервисам, например личному OneDrive.
Более подробно про Work и Personal аккаунты можно почитать тут “Understanding Microsoft Work And Personal Accounts”.
Office 365 API (например Microsoft Graph API) имеет разную поддержку для персональных и рабочих аккаунтов. Например, работать с почтой могут и Work account и Personal account, но не существует персонального SharePoint (а следовательно, и API SharePoint для Personal account).
Мы уже знаем, что token для вызовов API выдает “Azure AD Authorization Endpoint”. Точек авторизации существует 2:
- Authorization Endpoint
Выдает токены только для Work Account-ов.
При логине пользователь отправляется на
https: //login.microsoftonline.com/common/oauth2/authorize?client_id=... - Authorization Endpoint v2.0
Выдает токены как для Work так и для Personal Account-ов
При логине пользователь отправляется на
https: //login.microsoftonline.com/common/oauth2/v2.0/authorize?
client_id=…
Зачем тогда вообще нужен “Authorization Endpoint”? Особенность заключается в том, что “Authorization Endpoint v2.0” выдаст токен только для тех возможностей API которые есть и для Work и для Personal аккаунтов. Т.е. используя Endpoint v2.0 и Work account вы сможете получить доступ к почте, но не будет доступа к API SharePoint (подробнее о том какие API поддерживает Endpoint v2.0 см в ссылках в конце).
В настоящее время v2.0 endpoint не работает с приложениями, которые зарегистрированы в корпоративном Azure портале (такую регистрацию мы делали в прошлой заметке), нужно использовать отдельный Microsoft Application Registration Portal.
Microsoft обещает в будущем расширить возможности v2.0 endpoint, и обеспечить поддержку приложений, зарегистрированных в корпоративном Azure портале — v2.0 endpoint сможет выдать для них токены. А пока, для корпоративных приложений, Microsoft рекомендует использовать “Authorization Endpoint”:
If your application only needs to support Microsoft work and school accounts, don't use the v2.0 endpoint
ADAL JS работает с “Authorization Endpoint”, MSAL JS с v2.0 endpoint. В данной заметке мы будем использовать Authorization Endpoint первой версии и соответственно ADAL JS.
Angular 5 и ADAL JS
Нам понадобится установленный Node.js, npm, и Angular CLI – утилита которая помогает создавать и собирать Angular проекты. Весь процесс хорошо описан в Angular QuickStart.
Сделаем новый проект:
ng new angular5-office365-adal-example
Не существует официальных (от Microsoft) TypeScript d.ts описаний для Adal.js. Несколько вариантов использования Adal.js в Angular 5:
- Не использовать d.ts описания, объявить объект AuthenticationContext (из Adal.js) как глобальный any и писать нетипизированный код как на обычном JavaScript
- Самому сделать d.ts описание
- Воспользоваться проектом adal-angular5, который является калькой оригинального adal-angular.js для AngularJS от Microsoft (Adal js)
- Есть проекты, в которых Adal js полностью переписан на TypeScript (adal-ts, adal-typescript)
- Воспользоваться готовым d.ts описанием.
5 вариант выглядит самым простым и удобным: используется оригинальный Adal.js от Microsoft и с помощью d.ts описания добавляете intellisense и проверки при сборке.
Установим проверенные d.ts описания для Adal.js. Находясь в папке проекта:
npm install --save @types/adal
У нас пример тестовый, поэтому сделаем его максимально простым: будем подключаться к Microsoft Graph API прямо в AppComponent.
В файле app.component.ts импортируем HttpClient и adal
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { } from 'adal'; // без этого приложение будет собираться, но будут сообщения об ошибках
В app.module.ts подключим HttpClientModule
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http'; //<- ADD import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule //<- ADD ], providers: [], bootstrap: [AppComponent]
})
export class AppModule { }
Подключим js-библиотеку к странице
Дальше будет точно такой же код как в прошлом примере на JS.
В ngOnInit проверим авторизован пользователь или нет, если не авторизован или token протух отправим пользователя на страницу регистрации.
let config: adal.Config = { tenant: 'igtit.onmicrosoft.com', clientId: '21XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', postLogoutRedirectUri: window.location.origin, endpoints: { graphApiUri: "https://graph.microsoft.com", }, cacheLocation: "localStorage", redirectUri: ''
}; let authContext = new AuthenticationContext(config); let isCallback = authContext.isCallback(window.location.hash);
authContext.handleWindowCallback(); if (isCallback && !authContext.getLoginError()) { window.location.href = (<any>authContext)._getItem((<any>authContext).CONSTANTS.STORAGE.LOGIN_REQUEST);
} // check if user need to login
let user = authContext.getCachedUser();
let token = authContext.getCachedToken(config.clientId);
if (!user || !token) { authContext.login();
}
Теперь можно использовать token для вызова Microsoft Graph API
authContext.acquireToken(config.endpoints.graphApiUri, (error, token) => { // call Microsoft Graph API with token let url = config.endpoints.graphApiUri + "/v1.0/me/messages"; this.http.get(url, { headers: { "Authorization": "Bearer " + token } }).subscribe(mgs => this.messages = (<any>mgs).value); });
Полный пример на GitHab.
Ссылки
Active Directory Authentication Library (ADAL) for JavaScript
Microsoft Authentication Library Preview for JavaScript (MSAL.js)
Should I use the v2.0 endpoint?
What's different about the v2.0 endpoint?
Understanding Microsoft Work And Personal Accounts