Мой главный вопрос: как при работе с Exchange Online должна работать потоковая подписка по отношению к периодическому обновлению токена доступа?
Подробности: я использую подписки на потоковую передачу EWS в течение некоторого времени для локального Exchange. Следуя обычному процессу, я создаю StreamingSubscriptionConnection
, добавляю к нему подписки на почтовый ящик, а затем открываю соединение. Когда возникает событие OnDisconnect
, мы повторно открываем соединение.
Мы реализовали подписку на потоковую передачу для почтовых ящиков в Exchange Online, которая требует от нас использования современной проверки подлинности с Microsoft.Identity.Client. Как указано в этом page, мы принудительно обновляем токен доступа каждые 30 минут в фоновом потоке.
Все отлично работает, пока мы не обновим токен доступа. В этот момент, когда срабатывает событие соединения OnDisconnect
, и мы пытаемся повторно открыть соединение, происходит сбой 401 Unauthorized. В настоящее время у нас есть переназначение свойства Credentials
объекта ExchangeService
после обновления токена, но это, похоже, не оказывает никакого влияния на объекты StreamingSubscriptionConnection
, которые были созданы до обновления токена.
Обратите внимание, что у класса StreamingSubscriptionConnection
нет свойства Credentials
, которое мы можем сбросить после обновления токена. Как объект подключения должен получать обновленные учетные данные?
Спасибо!
Джон
ОБНОВЛЕНИЕ
Оказывается, я не обновлял свойство Credentials
объекта ExchangeService
после обновления токена. Как только я разобрался с этим, повторное открытие соединения работает нормально.
Для всех, кому может быть интересно, вот как мы это делаем. Сначала определите объемы:
private string[] ewsScopes = new string[] { "https://outlook.office.com/.default" };
Теперь получите токен доступа:
_app = ConfidentialClientApplicationBuilder.Create(_EXOAppId)
.WithAuthority(AzureCloudInstance.AzurePublic, _EXOTenantId)
.WithClientSecret(_EXOClientSecret)
.Build();
TokenCacheHelper.EnableSerialization(_app.AppTokenCache);
_EXOAuthResult = await _app.AcquireTokenForClient(ewsScopes).ExecuteAsync();
Затем установите таймер для периодического обновления токена (мы делаем это каждые 30 минут):
_nextRefresh = DateTime.Now.AddMinutes(refreshInterval);
_refreshTimer = new System.Timers.Timer();
_refreshTimer.Interval = 1000;
_refreshTimer.Elapsed += _refreshTimer_Elapsed;
_refreshTimer.Start();
И истекшее событие таймера:
private async void _refreshTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (DateTime.Now < _nextRefresh) return;
_refreshTimer.Stop();
_EXOAuthResult = await _app.AcquireTokenForClient(ewsScopes)
.WithForceRefresh(true) // Do NOT force refresh every time!!
.ExecuteAsync();
//--> Here is where you would update the Credentials property of your ExchangeService
_nextRefresh = DateTime.Now.AddMinutes(refreshInterval);
_refreshTimer.Start();
}
Вот в основном это. Вам просто нужно убедиться, что вы правильно кешируете токен, что должно быть сделано с помощью TokenCacheHelper.