401 使用EWS一段时间后出错

问题描述 投票:0回答:1

我的应用程序在一段时间后出现 401 错误(我相信是由于令牌过期)。我的 Exchange 连接代码是:

每次用户执行与 EWS 相关的任何操作(即在 CRM 程序中选择电子邮件)时,都会调用 Connect。

Public Shared Function Connect() As ExchangeService
    app = PublicClientApplicationBuilder.Create(ClientID).WithAuthority(Authority).WithRedirectUri(RedirectUri).Build()

    ' Authenticate the user and get the ExchangeService object
    Dim ewsService As ExchangeService = InitializeEwsService()

    ' Return the initialized ExchangeService object
    Return ewsService
End Function

初始化Ews服务:

        Private Shared Function InitializeEwsService() As ExchangeService
            Authenticate() ' Ensure authentication before initializing EWS

            Dim ewsService As New ExchangeService(ExchangeVersion.Exchange2013)
            ewsService.Url = New Uri(EwsUrl)
            ewsService.Credentials = New OAuthCredentials(authenticationResult.AccessToken)
            Return ewsService
        End Function
Private Shared Sub Authenticate()
    Try
        ' Check if we already have a valid token
        If authenticationResult Is Nothing OrElse authenticationResult.ExpiresOn.UtcDateTime <= DateTime.UtcNow Then
            ' Attempt silent authentication
            Try
                authenticationResult = app.AcquireTokenSilent(Scopes, authenticationResult.Account).ExecuteAsync().Result
            Catch ex As MsalUiRequiredException
                ' Silent authentication failed, fallback to interactive login
                Try
                    authenticationResult = app.AcquireTokenInteractive(Scopes).ExecuteAsync().Result
                Catch interactiveEx As Exception
                    ' Handle authentication error
                    Throw New Exception("Interactive authentication failed: " & interactiveEx.Message)
                End Try
            Catch ex As Exception
                ' Silent authentication failed, fallback to interactive login
                authenticationResult = app.AcquireTokenInteractive(Scopes).ExecuteAsync().Result


            End Try
        End If
    Catch ex As AggregateException
        ' Handle authentication error
        Throw New Exception("Authentication failed: " & ex.InnerException.Message)
    End Try
End Sub

我什至尝试过对所有内容进行粗略重置,当触发 emailRead 代码时,它会捕获 401 错误并运行 Handle401 函数来清除所有内容,但即使在登录后,它也会陷入 401Handle 错误的循环中。

我还注意到登录是不同的,当应用程序首次加载时,用户必须输入密码,然后执行 MFA,大约一个小时后,用户确实会出现登录窗口,但他们单击电子邮件并且永远不会提示输入密码,直接导致 401 错误,就好像过期的令牌永远不会被刷新,但我不知道我错过了什么?

vb.net exchangewebservices office365api
1个回答
0
投票

如果您想要续订令牌,则需要使用 MSAL 令牌缓存,请参阅 https://learn.microsoft.com/en-us/entra/msal/dotnet/acquiring-tokens/acquire-token-silently 所以这个

app = PublicClientApplicationBuilder.Create(ClientID).WithAuthority(Authority).WithRedirectUri(RedirectUri).Build()

只应创建一次,否则您将没有缓存可供使用,为每个 EWS 请求执行 InitializeEwsService 都可以,但在这种情况下我会这样做

If authenticationResult Is Nothing OrElse authenticationResult.ExpiresOn.UtcDateTime <= DateTime.UtcNow Then

这不是必需的,因为当您调用 app.AcquireTokenSilent 时,MSAL 将处理令牌过期和续订,如果令牌不存在,它将获取一个新令牌;如果存在,则使用缓存的令牌;或者从刷新令牌续订缓存的令牌如果过期了。

EWS 托管 API 的一个问题是它不提供身份验证回调,每次重新创建 ExchangeService 应该可以工作,但如果您这样做,我建议您让 Authenticate 返回访问令牌,而不是在authenticationResult 的范围内调用 AcquireToken应该只是功能级别。

您可以修改 EWS 托管 API 的源,以使 ExchangeService 回调每次都检查 MSAL 令牌缓存,这使您的代码更加高效和可读,请参阅 https://github.com/gscales/EWS-BasicToOAuth -Info/blob/main/EWA%20Managed%20API%20MASL%20Token%20Refresh.md

© www.soinside.com 2019 - 2024. All rights reserved.