【问题标题】:ews streaming connection reconnect with oAuth2使用 oAuth2 重新连接 ews 流连接
【发布时间】:2020-10-14 09:58:20
【问题描述】:

我正在重写使用 EWS 流连接监控邮箱的后端服务,我正在将其从基本身份验证更改为 oAuth2。

一切正常,在服务启动时我订阅了邮箱,它创建了一个交换服务,检索一个身份验证令牌,然后监视邮箱 30 分钟,直到流连接到期。我有一个事件处理程序附加到订阅的 OnDisconnect 事件以自动重新连接。这也有效。但是,oAuth2 令牌的生命周期为 1 小时。所以第二次流连接尝试重新连接它失败并出现未经授权的错误代码。

当流连接超时时,如何强制它更新 oAuth 令牌并使用更新的令牌每 30 分钟重新连接一次?

这是我的代码:

获取身份验证令牌:

    Public Async Function getTokenAsync() As Task(Of String)

    Try
        Dim authority As String = ConfigurationManager.AppSettings("AuthorizationUri").Replace("common", "xxxxxxxxxxxxxxx")
        Dim authenticationContext As Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext = New Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(authority, False)
        Dim certfile As String = "D:\DevRepos\Test apps\oAuth2 EWS test app\testCert.pfx"
        Dim cert As X509Certificate2 = New X509Certificate2(certfile, "xxxx", X509KeyStorageFlags.MachineKeySet)
        Dim cac As Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate = New Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate("xxxxxxxxxxxx", cert)
        Dim authenticationResult = Await authenticationContext.AcquireTokenAsync("https://outlook.office365.com", cac)

        Return authenticationResult.AccessToken

    Catch ex As Exception
        MsgBox(ex.ToString)
    End Try


    Return Nothing

End Function

创建 Exchange 服务:

    Public Async Function exchangeServiceconnection() As Task(Of ExchangeService)
    Dim test As Task(Of String)
    test = getTokenAsync()
    Dim result2 As String = Await test
    Dim ewsClient = New ExchangeService()

    Try
        ewsClient.Url = New Uri("https://outlook.office365.com/EWS/Exchange.asmx")
        ewsClient.Credentials = New OAuthCredentials(result2)
        ewsClient.ImpersonatedUserId = New ImpersonatedUserId(ConnectingIdType.SmtpAddress, "mailbox@testdomain.com")
        ewsClient.HttpHeaders.Add("X-AnchorMailbox", "mailbox@testdomain.com")

    Catch ex As MsalException
        MsgBox($"Error acquiring access token: {ex.ToString()}")
    Catch ex As Exception
        MsgBox($"Error: {ex.ToString()}")
    End Try

    Return ewsClient

End Function

订阅邮箱:

    Async Sub Subscribe()
    Dim service As ExchangeService
    service = Await exchangeServiceconnection()
    Dim locateMailbox = New Mailbox With {
        .Address = "mailbox@testdomain.com"
    }
    Dim folderId = New FolderId(WellKnownFolderName.Inbox, locateMailbox)
    Dim foldersToWatch = {folderId}
    Dim streamingSubscription As StreamingSubscription = service.SubscribeToStreamingNotifications(foldersToWatch, EventType.NewMail)
    Dim streamingConnection = New StreamingSubscriptionConnection(service, 30)
    streamingConnection.AddSubscription(streamingSubscription)
    AddHandler streamingConnection.OnSubscriptionError, AddressOf ResolveError
    AddHandler streamingConnection.OnDisconnect, AddressOf Reconnect
    AddHandler streamingConnection.OnNotificationEvent, AddressOf Form1.message
    streamingConnection.Open()
End Sub

重新连接处理程序:

    Public Sub Reconnect(ByVal sender As Object, ByVal disconnectEventArgs As SubscriptionErrorEventArgs)
    If Not CType(sender, StreamingSubscriptionConnection).IsOpen Then
        CType(sender, StreamingSubscriptionConnection).Open()
    End If
End Sub

出错时重新连接:

    Public Sub ResolveError(ByVal sender As Object, ByVal errorEventArgs As SubscriptionErrorEventArgs)
    Dim streamingSubscriptionConnection = CType(sender, StreamingSubscriptionConnection)
    If Not streamingSubscriptionConnection.IsOpen Then streamingSubscriptionConnection.Open()
End Sub

【问题讨论】:

    标签: vb.net oauth-2.0 exchangewebservices


    【解决方案1】:

    所以我在我的重新连接功能中执行了以下操作,公开了交换服务,在重新连接时请求新的身份验证令牌并使用新令牌更新服务凭据。

    现在似乎工作正常,服务已经运行了一夜没有问题。

        Public Async Sub Reconnect(ByVal sender As Object, ByVal disconnectEventArgs As SubscriptionErrorEventArgs)
        If Not CType(sender, StreamingSubscriptionConnection).IsOpen Then
            Dim test As Task(Of String)
            test = getTokenAsync()
            result2 = Await test
            service.Credentials = New OAuthCredentials(result2)
            CType(sender, StreamingSubscriptionConnection).Open()
        End If
    End Sub
    

    这解决了我的问题,如果有更好的方法请评论

    【讨论】:

    • 所以这工作了大约一天然后失败,如果我在某个时候查看日志它不会刷新令牌然后无法重新打开连接。但在此之前,我可以看到它每小时刷新一次令牌。如何强制它刷新令牌?
    【解决方案2】:

    我已经设法摆脱了处理 HTTP 401 并返回 OAuth 以获取新令牌。

    【讨论】:

    • 感谢 pjneary,我也做了同样的事情,现在看起来很稳定,每 30 分钟更新一次令牌。你介意分享你的代码吗?我在下面提出了我的,它有效,但不确定这是否是最好的方法。
    猜你喜欢
    • 1970-01-01
    • 2017-10-28
    • 2021-12-14
    • 2010-09-06
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 2018-04-12
    • 2010-11-23
    相关资源
    最近更新 更多