Доступ к API графика календаря Outlook из фоновой службы

Я работаю над веб-приложением (SPA и серверной частью), которое должно постоянно получать доступ к календарю Outlook пользователя. Пользователи могут заходить из нескольких каталогов и личных учетных записей. Приложение будет работать круглосуточно, 7 дней в неделю, запуская фоновую службу и изменяя календарь пользователя без участия пользователя. На данный момент я выполнил следующее:

  1. Я создал регистрацию приложения AAD с поддерживаемыми типами учетных записей «Учетные записи в любом каталоге организации (любой клиент Microsoft Entra ID — мультитенант) и личные учетные записи Microsoft (например, Skype, Xbox)».

  2. Я установил RedirectURI в качестве базового URL-адреса SPA и создал секрет.

  3. Я реализовал аутентификацию в 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...

  4. После того, как пользователь успешно пройдет аутентификацию и предоставит все разрешения, его учетная запись будет выглядеть как

  5. Я также получил tenantId из токена идентификатора (заявление tid).

  6. Просто чтобы убедиться, что мой access_token действителен и разрешения установлены правильно, я успешно запросил события из https://graph.microsoft.com/v1.0/me/events На этом этапе я предполагаю, что пользователь успешно предоставил все необходимые разрешения для моего приложения, и моя фоновая служба может получить доступ к календарю пользователя

  7. Я успешно запросил 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:


1
134
3

Ответы:

Попробуйте удалить требование согласия администратора.


Решено

Я создал мультитенантное приложение 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 из фоновой службы. Что мы знаем на данный момент:

  • Мы не можем использовать «поток учетных данных клиента», поскольку он недоступен для личных учетных записей.
  • Мы не можем использовать «поток кода авторизации», поскольку в фоновой службе нет пользователя, с которым можно было бы взаимодействовать.

Таким образом, предлагаемое решение заключается в следующем:

  1. Пользователь личного кабинета должен хотя бы один раз войти в приложение, чтобы предоставить приложению разрешение на доступ к календарю и профилю пользователя. Для этого мы используем «поток кода авторизации».
  2. Когда мы обмениваем код на токен, мы получаем не только access_token, но иrefresh_token. Мы надежно хранимrefresh_token где-то на сервере.
  3. Когда фоновой службе требуется доступ к API Graph (без участия пользователя), она обмениваетrefresh_token на access_token.
  4. Фоновая служба периодически должна получать новый Referh_token, поскольку срок его действия истекает через 90 дней, согласно https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens