Я работаю над веб-приложением (SPA и серверной частью), которое должно постоянно получать доступ к календарю Outlook пользователя. Пользователи могут заходить из нескольких каталогов и личных учетных записей. Приложение будет работать круглосуточно, 7 дней в неделю, запуская фоновую службу и изменяя календарь пользователя без участия пользователя. На данный момент я выполнил следующее:
Я создал регистрацию приложения AAD с поддерживаемыми типами учетных записей «Учетные записи в любом каталоге организации (любой клиент Microsoft Entra ID — мультитенант) и личные учетные записи Microsoft (например, Skype, Xbox)».
Я установил RedirectURI в качестве базового URL-адреса SPA и создал секрет.
Я реализовал аутентификацию в SPA с помощью MSAL (msal-браузер). Мой запрос на авторизацию выглядит так: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?scope=https://graph.microsoft.com/Calendars.ReadWrite+openid+profile+offline_access&response_type =code&client_id=my_client_id...
После того, как пользователь успешно пройдет аутентификацию и предоставит все разрешения, его учетная запись будет выглядеть как
Я также получил tenantId из токена идентификатора (заявление tid).
Просто чтобы убедиться, что мой access_token действителен и разрешения установлены правильно, я успешно запросил события из https://graph.microsoft.com/v1.0/me/events На этом этапе я предполагаю, что пользователь успешно предоставил все необходимые разрешения для моего приложения, и моя фоновая служба может получить доступ к календарю пользователя
Я успешно запросил access_token с потоком client_credentials.
curl --location 'https://login.microsoftonline.com/tenantId_from_step_5/oauth2/v2.0/token'
--header 'Тип контента: application/x-www-form-urlencoded'
--data-urlencode 'client_id=clientId_from_step1'
--data-urlencode 'scope=https://graph.microsoft.com/.default'
--data-urlencode 'client_secret=secret_from_step2'
--data-urlencode 'grant_type=client_credentials'
Я запросил события пользователя с помощью access_token, полученного на предыдущем шаге https://graph.microsoft.com/v1.0/users/[email protected]/events, но получил следующую ошибку
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again."
}
}
Я застрял на этом этапе и буду признателен за любую помощь или предложения.
ОБНОВЛЯТЬ:
Токен JWT, полученный с помощью credential_flow (шаг 7 сверху) из https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/oauth2/v2.0/token, пропускает роли (разрешения)
Я думаю, что все личные учетные записи имеют один и тот же tenantId=9188040d-6c67-4c5b-b112-36a304b66dad
Разрешения моего приложения (outlook-sync-dev) на портале Azure:
Я создал мультитенантное приложение Microsoft Entra и предоставил разрешение API, как показано ниже:
Сгенерированный токен доступа через поток учетных данных клиента:
https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/oauth2/v2.0/token
client_id:ClientID
client_secret:ClientSecret
scope↵:https://graph.microsoft.com/.default
grant_type:client_credentials
Используя указанный выше токен доступа, я попытался вызвать API событий для личной учетной записи и получил ту же ошибку:
https://graph.microsoft.com/v1.0/users/UserID/events
Обратите внимание: поток учетных данных клиента не поддерживает личные учетные записи Microsoft. Следовательно, вы должны использовать любой поток взаимодействия с пользователем для вызова API, связанных с личной учетной записью, то есть пользователь должен выполнить процесс входа в систему.
Следовательно, чтобы устранить ошибку, используйте поток кода авторизации:
Предоставьте делегированные разрешения API:
Сгенерируйте код авторизации:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
&client_id=ClientID
&response_type=code
&redirect_uri=https://jwt.ms
&response_mode=query
&scope=https://graph.microsoft.com/.default offline_access
&state=12345
И войдите в личный кабинет:
Сгенерированный токен доступа. Поток кода авторизации:
https://login.microsoftonline.com/common/oauth2/v2.0/token
grant_type:authorization_code
client_id:ClientID
client_secret:ClientSecret
scope:https://graph.microsoft.com/.default offline_access
code:Code
redirect_uri:https://jwt.ms
Я могу успешно вызывать API событий:
https://graph.microsoft.com/v1.0/users/UserID/events
Чтобы выполнить тот же JavaScript, обратитесь к этому документу Получите токен для вызова веб-API (одностраничные приложения) — платформа идентификации Microsoft | Майкрософт
Ссылка:
Исключения в MSAL Java — библиотека проверки подлинности Microsoft для Java | Майкрософт
Я думаю, что ответ @Rukmini правильный, но опускает некоторые неочевидные детали. Я хотел добавить разъяснения в комментарий, но он слишком длинный, поэтому добавляю ответ.
Мой первоначальный вопрос касался доступа к календарю Outlook (личной учетной записи) через Graph API из фоновой службы. Что мы знаем на данный момент:
Таким образом, предлагаемое решение заключается в следующем: