【发布时间】:2020-10-08 14:40:06
【问题描述】:
我的主要问题:使用 Exchange Online,流订阅应该如何与定期访问令牌刷新相关?
详情:
一段时间以来,我一直在使用 EWS 流订阅进行本地 Exchange。按照通常的过程,我创建了一个StreamingSubscriptionConnection,向其中添加邮箱订阅,然后打开连接。当OnDisconnect 事件触发时,我们重新打开连接。
我们现在已经在 Exchange Online 中实现了邮箱的流式订阅,这需要我们将 Modern Auth 与 Microsoft.Identity.Client 一起使用。正如this page 所建议的那样,我们在后台线程上每 30 分钟强制刷新一次访问令牌。
一切正常,直到我们刷新访问令牌。那时,当连接的OnDisconnect 事件触发时,我们尝试重新打开连接,它会失败并显示 401 Unauthorized。我们目前在刷新令牌后重新分配ExchangeService 对象的Credentials 属性,但这似乎对刷新令牌之前创建的StreamingSubscriptionConnection 对象没有任何影响。
注意StreamingSubscriptionConnection 类没有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 完成。
【问题讨论】:
标签: streaming exchange-server exchangewebservices subscription msal