使用 Exchange Online 的 EWS 流媒体订阅

EWS Streaming Subscription with Exchange Online

我的主要问题:使用 Exchange Online,流式订阅应该如何与定期访问令牌刷新相关联?

详情: 一段时间以来,我一直在使用 EWS 流媒体订阅来进行本地 Exchange。按照通常的过程,我创建了一个 StreamingSubscriptionConnection,向其中添加邮箱订阅,然后打开连接。当 OnDisconnect 事件触发时,我们重新打开连接。

我们现在已经在 Exchange Online 中实现了邮箱的流式订阅,这需要我们使用具有 Microsoft.Identity.Client 的现代身份验证。根据 this page 上的建议,我们强制在后台线程上每 30 分钟刷新一次访问令牌。

一切正常,直到我们刷新访问令牌。那时,当连接的 OnDisconnect 事件触发时,我们尝试重新打开连接,但失败并返回 401 Unauthorized。我们目前在刷新令牌后重新分配 ExchangeService 对象的 Credentials 属性,但这似乎对 StreamingSubscriptionConnection 对象没有任何影响这是在刷新令牌之前创建的。

请注意 StreamingSubscriptionConnection class 没有我们可以在令牌刷新后重置的 Credentials 属性。连接对象应该如何获得更新的凭据?

谢谢!

约翰

更新

事实证明,刷新令牌后我实际上并没有更新 ExchangeService 对象的 Credentials 属性。排序后,重新打开连接就可以正常工作。

对于可能感兴趣的任何人,我们是这样做的。首先定义范围:

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();

以及定时器 Elapsed 事件:

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 完成。

事实证明,在刷新令牌后我实际上并没有更新 ExchangeService 对象的凭据 属性。一旦我完成排序,重新打开连接就可以正常工作了。