Доступ к 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:

Пожалуйста, проверьте свой токен доступа, вставив его в jwt.ms

Shiva Keshav Varma 06.07.2024 03:52

Я обновил свой вопрос скриншотом. Токен JWT пропускает роли по непонятным мне причинам.

monofilm 06.07.2024 08:19

@monofilm Проблема решена?

Rukmini 15.07.2024 05:52

@Rukmini Это решено. Я получил ответ на другой платформе Learn.microsoft.com/en-us/answers/questions/1792233/… Похоже, поток учетных данных невозможен для личных учетных записей. Решение состоит в том, чтобы захватить обновить_токен во время первоначального входа пользователя в систему и использовать его в фоновой службе для получения доступа_токена. Я колебался, стоит ли мне помещать это здесь в качестве ответа, поскольку я еще не тестировал этот подход.

monofilm 15.07.2024 08:16

@Рукмини, конечно можешь

monofilm 15.07.2024 08:19

@Rukmini Я добавил дополнительную информацию в другой ответ. Кажется, комментарий слишком длинный

monofilm 15.07.2024 12:00

Вы хотите обновить токен доступа?

Rukmini 15.07.2024 12:04

Да, я обновляю токен доступа. Я не могу найти другого способа, чтобы фоновая служба сохраняла доступ к календарю, принадлежащему личному аккаунту.

monofilm 15.07.2024 12:23

Вы хотите добиться этого через Postman?

Rukmini 15.07.2024 12:35

Конечно, нет, поскольку я обновляю токен доступа из фоновой службы. Я сделал скриншот из почтальона, чтобы продемонстрировать, как должен выглядеть запрос. В реальной жизни это будет код C#.

monofilm 15.07.2024 12:45

Я был бы рад принять решение. К сожалению, ни один из ответов здесь не является полным. И это, на мой взгляд, было бы заблуждением

monofilm 15.07.2024 19:26

@monofilm Пожалуйста, опубликуйте новый вопрос о том, как обрабатывать токен обновления в C# со всеми подробностями, поскольку первоначальное требование об ошибке потока учетных данных клиента публикуется в качестве ответа.

Rukmini 16.07.2024 09:08

@Rukmini, возможно, у нас тут недопонимание. Я знаю, как обращаться с токенами обновления, и мне не нужна в этом помощь.

monofilm 16.07.2024 11:50

Хорошо, каковы ваши точные требования? @monofilm

Rukmini 16.07.2024 11:51

@Rukmini, прошу прощения, если непреднамеренно запутал обсуждение. Я изложил точные требования в первых трех предложениях своих первоначальных вопросов. Остальное — описание моей неудачной попытки реализовать эти требования. Мне посчастливилось получить помощь на другой платформе (ссылку я поделился ранее), что заставило меня понять, что весь подход с использованием «потока учетных данных клиента» не будет работать. Я нашел другой способ, о котором упоминал в своем ответе. Я благодарен за вашу помощь, но у меня больше нет вопросов, если вы не знаете лучший способ удовлетворить мои требования.

monofilm 16.07.2024 12:34

@monofilm Обходной путь, который вы упомянули в ответе, работает, и это хороший подход, никаких изменений не требуется, а также какие-либо другие требования/разъяснения?

Rukmini 16.07.2024 12:49

@Рукмини, все хорошо. Спасибо!

monofilm 16.07.2024 18:55
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
1
17
134
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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 | Майкрософт

Это верно. Если кто-то все еще не понимает, как получить доступ к календарю личного кабинета Outlook, рекомендую посмотреть stackoverflow.com/a/78749233/875010

monofilm 16.07.2024 19:01

Я думаю, что ответ @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

Другие вопросы по теме