Web API, вызываемый из веб-приложения. Перед веб-API стоит задача получить доступ к Imap для внешних пользователей для непрерывного чтения их электронной почты с помощью MailKit.
Это включает в себя перенаправление пользователей к их поставщику электронной почты, например, Google или Microsoft/Outlook/Exchange/Office365 аутентификация. страница.
После того, как пользователь войдет в систему и предоставит необходимое согласие на доступ к своей электронной почте, приложение Web Api получит учетные данные, которые будут использоваться для постоянно отслеживать свою электронную почту без дальнейшего вмешательства пользователя.
В случае Gmail учетные данные, полученные в процессе аутентификации, имеют форму токен обновления. Он используется для получения токена доступа по истечении срока действия токена доступа.
В Microsoft учетные данные представлены в форме объекта IAccount.
Для Microsoft также существует Кэш токенов, откуда необходимый токен доступа извлекается с помощью вышеупомянутого объекта IAccount.
С Gmail у меня нет проблем. Все идет гладко.
Однако с Microsoft все совсем по-другому.
Мне пока удается пройти дальше первого шага, т.е. интерактивного получения пользователю пройти аутентификацию и предоставить доступ к своей электронной почте. Я также могу использовать полученные учетные данные объекта IAccount для возобновления доступа автоматически (т. е. без взаимодействия с пользователем). Это работает, даже если приложение остановлено и перезапущено.
Большая проблема начинается примерно через 20 часов, когда я получаю исключение MsalUiRequiredException «Срок действия гранта истек». По сути, это означает, что мне нужно заставить пользователя пройти процедуру аутентификации/предоставления/согласия заново.
Вот несколько выдержек из кода, который я использую:
Код: Выделить всё
// Obtain (First stage) credentials interactively
var pca = PublicClientApplicationBuilder
.Create(microsoftClientId)
.WithAuthority(AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount)
.WithRedirectUri(redirectUri)
.Build();
result = await pca.AcquireTokenInteractive(_scopes)
.WithSystemWebViewOptions(new SystemWebViewOptions
{
HtmlMessageError = "
An error occurred: {0}. Details {1}
",
BrowserRedirectSuccess = new Uri("https://xxxxxxx xxxxx xxxx_thanks-for-consent-page")
})
.WithExtraHttpHeaders(new Dictionary {
{ "Origin", "http://localhost,https://localhost" },
{ "Access-Control-Allow-Origin", "*" } })
.WithUseEmbeddedWebView(false)
.WithPrompt(Prompt.Consent)
.ExecuteAsync(timerTokenSource.Token);
Код: Выделить всё
refresh = await pca
.AcquireTokenSilent(_scopes, account)
.WithExtraHttpHeaders(new Dictionary {
{ "Origin", "http://localhost,https://localhost" },
{ "Access-Control-Allow-Origin", "*" } })
.WithTenantId("common")
.ExecuteAsync();
Код: Выделить всё
account
Поскольку я контролирую постоянство кэша токенов, я точно знаю, что необходимый токен доступен для вышеуказанного AcquireTokenSilent.
И снова этот метод будет работать нормально около 20 часов, а после этого произойдет сбой с ужасной MsalUiRequiredException.
Кто-нибудь сталкивался с таким?
Что-то я делаю не так?
Обратите внимание: я не хочу идти по маршруту Microsoft.Identity.Web, так как в веб-приложении (том, которое использует эту службу веб-API) пользователь может в принципе войти в систему с помощью другие учетные данные, кроме электронного письма, по которому он хочет, чтобы мои API для мониторинга. Я хочу иметь возможность предоставить пользователю кнопку «Разрешить доступ к электронной почте» вместо кнопки «Войти».
Подробнее здесь: https://stackoverflow.com/questions/792 ... uiredexcep