Я работаю над веб-приложением (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:
Я обновил свой вопрос скриншотом. Токен JWT пропускает роли по непонятным мне причинам.
@monofilm Проблема решена?
@Rukmini Это решено. Я получил ответ на другой платформе Learn.microsoft.com/en-us/answers/questions/1792233/… Похоже, поток учетных данных невозможен для личных учетных записей. Решение состоит в том, чтобы захватить обновить_токен во время первоначального входа пользователя в систему и использовать его в фоновой службе для получения доступа_токена. Я колебался, стоит ли мне помещать это здесь в качестве ответа, поскольку я еще не тестировал этот подход.
@Рукмини, конечно можешь
@Rukmini Я добавил дополнительную информацию в другой ответ. Кажется, комментарий слишком длинный
Вы хотите обновить токен доступа?
Да, я обновляю токен доступа. Я не могу найти другого способа, чтобы фоновая служба сохраняла доступ к календарю, принадлежащему личному аккаунту.
Вы хотите добиться этого через Postman?
Конечно, нет, поскольку я обновляю токен доступа из фоновой службы. Я сделал скриншот из почтальона, чтобы продемонстрировать, как должен выглядеть запрос. В реальной жизни это будет код C#.
Я был бы рад принять решение. К сожалению, ни один из ответов здесь не является полным. И это, на мой взгляд, было бы заблуждением
@monofilm Пожалуйста, опубликуйте новый вопрос о том, как обрабатывать токен обновления в C# со всеми подробностями, поскольку первоначальное требование об ошибке потока учетных данных клиента публикуется в качестве ответа.
@Rukmini, возможно, у нас тут недопонимание. Я знаю, как обращаться с токенами обновления, и мне не нужна в этом помощь.
Хорошо, каковы ваши точные требования? @monofilm
@Rukmini, прошу прощения, если непреднамеренно запутал обсуждение. Я изложил точные требования в первых трех предложениях своих первоначальных вопросов. Остальное — описание моей неудачной попытки реализовать эти требования. Мне посчастливилось получить помощь на другой платформе (ссылку я поделился ранее), что заставило меня понять, что весь подход с использованием «потока учетных данных клиента» не будет работать. Я нашел другой способ, о котором упоминал в своем ответе. Я благодарен за вашу помощь, но у меня больше нет вопросов, если вы не знаете лучший способ удовлетворить мои требования.
@monofilm Обходной путь, который вы упомянули в ответе, работает, и это хороший подход, никаких изменений не требуется, а также какие-либо другие требования/разъяснения?
@Рукмини, все хорошо. Спасибо!
Попробуйте удалить требование согласия администратора.
Я создал мультитенантное приложение 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
Я думаю, что ответ @Rukmini правильный, но опускает некоторые неочевидные детали. Я хотел добавить разъяснения в комментарий, но он слишком длинный, поэтому добавляю ответ.
Мой первоначальный вопрос касался доступа к календарю Outlook (личной учетной записи) через Graph API из фоновой службы. Что мы знаем на данный момент:
Таким образом, предлагаемое решение заключается в следующем:
Пожалуйста, проверьте свой токен доступа, вставив его в jwt.ms