0
votes

I have a service which communicates with outlook exchange online using EWS. This has OAuth authentication and for that AppID is registered on the Azure portal. I am able to generate access token and communicate with exchange online successfully.

However, randomly in between getting request time out while generating token using MSAL library method "confidentialClientApplication.AcquireTokenForClient".

Please note many call happens to my service from difference places so could it be due to many calls this is failing? I think retry logic is inbuilt with this and in logs also i see similar thing. What is the recommended way to handle this issue?

Access token code

private async Task<string> GetAccessToken()
{
     try
     {
     
         var confidentialClientApplication = ConfidentialClientApplicationBuilder.Create(ExchangeOnlineConfiguration.ClientId)
                                                            .WithTenantId(ExchangeOnlineConfiguration.TenantId)
                                                            .WithClientSecret(ExchangeOnlineConfiguration.ClientSecret)
                                                            .Build();
         var authenticationResult = await confidentialClientApplication.
             AcquireTokenForClient(new[] { ExchangeOnlineConfiguration.DefaultScope }).ExecuteAsync();

         var accessToken = authenticationResult.AccessToken;
         return accessToken;
     }
     catch (Exception ex)
     {
         ContentLogger.logger.Error($"GetAccessToken failed! Exception Details {ex} ");
         throw;
     }
 }

Exception:

GetAccessToken failed! Exception Details MSAL.Desktop.4.14.0.0.MsalServiceException:
ErrorCode: request_timeout
Microsoft.Identity.Client.MsalServiceException: Request to the endpoint timed out. ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Http.HttpManager.<ExecuteAsync>d_10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Http.HttpManager.<ExecuteWithRetryAsync>d8.MoveNext()
--- End of inner exception stack trace ---
at Microsoft.Identity.Client.Http.HttpManager.<ExecuteWithRetryAsync>d8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Http.HttpManager.<ExecuteWithRetryAsync>d8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Http.HttpManager.<SendPostAsync>d4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Http.HttpManager.<SendPostAsync>d3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.OAuth2.OAuth2Client.<ExecuteRequestAsync>d11`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.OAuth2.OAuth2Client.<GetTokenAsync>d10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.OAuth2.TokenClient.<SendHttpAndClearTelemetryAsync>d8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Identity.Client.OAuth2.TokenClient.<SendHttpAndClearTelemetryAsync>d8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.OAuth2.TokenClient.<SendTokenRequestAsync>d5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<SendTokenRequestAsync>d21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.<FetchNewAccessTokenAsync>d3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.<ExecuteAsync>d2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.ApiConfig.Executors.ConfidentialClientExecutor.<ExecuteAsync>d3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at GetAccessToken>d_11.MoveNext() in   
1

1 Answers

2
votes

Obtaining multiple tokens asynchronously does not seem to work. One Confidential Client Application for each token cache.

For Client Credentials flow a singleton should work fine. You are requesting tokens for an application, not for a user. There will only be 1 access token in the in-memory cache (for the app), irrespective of how many users and sessions there are

Note that you're not providing a token cache implementation, which means that MSAL will cache tokens in memory (in this case the one access token).

You can refer to this question.