Skip to content

[Bug] 'Microsoft.Identity.Client.MsalUiRequiredException' occured: AADSTS5000224: We are sorry, this resource is not available. #5251

@qinl-li

Description

@qinl-li

Library version used

4.66.1

.NET version

.Net6.0

Scenario

ConfidentialClient - service to service (AcquireTokenForClient)

Is this a new or an existing app?

The app is in production, I haven't upgraded MSAL, but started seeing this issue

Issue description and reproduction steps

We have enabled ESTS-r globally. And we are seeing the following errors across the board. Can you help to take a look?

2025-04-23T12:45:47 [msg:1bd9][deq:998c] MsalUiRequiredException ERROR: RegionalClientCertificateCredential acquire token for tenant "" with parent requst ID "" failed. Exception: 'Microsoft.Identity.Client.MsalUiRequiredException' occured: AADSTS5000224: We are sorry, this resource is not available. If you are seeing this message by mistake, please contact Microsoft support. Trace ID: 22c5042e-23b3-4157-a5d5-14e787cec700 Correlation ID: 3aefdc8a-a61a-42d6-9da2-d5df9639826f Timestamp: 2025-04-23 12:45:47Z.
Stack: at Microsoft.Identity.Client.OAuth2.OAuth2Client.ThrowServerException(HttpResponse response, RequestContext requestContext)
at Microsoft.Identity.Client.OAuth2.OAuth2Client.CreateResponse[T](HttpResponse response, RequestContext requestContext)
at Microsoft.Identity.Client.OAuth2.OAuth2Client.ExecuteRequestAsync[T](Uri endPoint, HttpMethod method, RequestContext requestContext, Boolean expectErrorsOn200OK, Boolean addCommonHeaders, Func2 onBeforePostRequestData) at Microsoft.Identity.Client.OAuth2.TokenClient.SendHttpAndClearTelemetryAsync(String tokenEndpoint, ILoggerAdapter logger) at Microsoft.Identity.Client.OAuth2.TokenClient.SendHttpAndClearTelemetryAsync(String tokenEndpoint, ILoggerAdapter logger) at Microsoft.Identity.Client.OAuth2.TokenClient.SendTokenRequestAsync(IDictionary2 additionalBodyParameters, String scopeOverride, String tokenEndpointOverride, CancellationToken cancellationToken)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.SendTokenRequestAsync(IDictionary2 additionalBodyParameters, CancellationToken cancellationToken) at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.GetAccessTokenAsync(CancellationToken cancellationToken, ILoggerAdapter logger) at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.ExecuteAsync(CancellationToken cancellationToken) at Microsoft.Identity.Client.Internal.Requests.RequestBase.<>c__DisplayClass11_1.<<RunAsync>b__1>d.MoveNext() --- End of stack trace from previous location --- at Microsoft.Identity.Client.Utils.StopwatchService.MeasureCodeBlockAsync(Func1 codeBlock)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.ApiConfig.Executors.ConfidentialClientExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenForClientParameters clientParameters, CancellationToken cancellationToken)
at AzureSearch.Identity.RegionalClientCertificateCredential.<>c__DisplayClass4_0.<b__0>d.MoveNext() in F:\dbs\el\mbas\Source\Common\Product\AzureSearch.Identity\RegionalClientCertificateCredential.cs:line 69

Relevant code snippets

public sealed class RegionalClientCertificateCredential : TokenCredential
    {
        private readonly IConfidentialClientApplication _confidentialClient;
        private readonly bool _sendCertificateChain;

        public RegionalClientCertificateCredential(
            string authority, string tenantId, string clientId, X509Certificate2 clientCertificate, string region, bool sendCertificateChain)
        {
            _confidentialClient = ConfidentialClientApplicationBuilder.Create(clientId)
                                    .WithAuthority(authority, tenantId)
                                    .WithCertificate(clientCertificate)
                                    .WithAzureRegion(region)
                                    .Build();
            Log.TraceVerbose($"{nameof(RegionalClientCertificateCredential)} is initialized with azure region {region}.");
            _sendCertificateChain = sendCertificateChain;
        }

        public override AccessToken GetToken(
            TokenRequestContext requestContext, CancellationToken cancellationToken) =>
                GetTokenAsync(requestContext, cancellationToken).GetAwaiter().GetResult();

        public override async ValueTask<AccessToken> GetTokenAsync(
            TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            AcquireTokenForClientParameterBuilder request = _confidentialClient.AcquireTokenForClient(requestContext.Scopes)
                                         .WithSendX5C(_sendCertificateChain);
            if (!String.IsNullOrEmpty(requestContext.TenantId))
            {
                request.WithTenantId(requestContext.TenantId);
            }

            if (!String.IsNullOrEmpty(requestContext.ParentRequestId) && Guid.TryParse(requestContext.ParentRequestId, out Guid guid))
            {
                request.WithCorrelationId(guid);
            }

            if (!String.IsNullOrEmpty(requestContext.Claims))
            {
                request.WithClaims(requestContext.Claims);
            }
            
            int maxRetries = 3;
            AuthenticationResult result = await Retry.ExecuteAsync<AuthenticationResult,Exception>(
                nameof(GetTokenAsync),
                async (attempt) =>
                {
                    Log.TraceVerbose($"Attempt {attempt}: {nameof(RegionalClientCertificateCredential)} start to acquire token for tenant \"{requestContext.TenantId}\" with parent requst ID \"{requestContext.ParentRequestId}\"");
                    try
                    {
                        return await request.ExecuteAsync(cancellationToken).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        Log.TraceException(ex, TraceEventType.Error, $"ERROR: {nameof(RegionalClientCertificateCredential)} acquire token for tenant \"{requestContext.TenantId}\" with parent requst ID \"{requestContext.ParentRequestId}\" failed. Exception: '{ex.GetType().FullName}' occured");
                        throw ex;
                    }
                },
                maxAttempts: maxRetries,
                shouldRetry: ex => { 
                    return IsMsalRetryableException(ex);
                },
                retryDelayEvaluator: Retry.ExponentialDelay(initialDelay: TimeSpan.FromMilliseconds(500)),
                cancellationToken: cancellationToken).ConfigureAwait(false);
            return new AccessToken(result.AccessToken, result.ExpiresOn);
        }

        //Following example from https://learn.microsoft.com/en-us/entra/msal/dotnet/advanced/exceptions/retry-policy#example-retry-policy to retry on retryable exceptions
        private bool IsMsalRetryableException(Exception ex)
        {
            bool isRetryable = false;
            if (ex is HttpRequestException)
            {
                isRetryable = true;
            } else if (ex is MsalException msalException && msalException.IsRetryable)
            {
                isRetryable = true;
            }
            if (isRetryable)
            {
                Log.TraceVerbose($"Will retry accquiring token later.");
            } else
            {
                Log.TraceVerbose($"Non-Retryable exception {ex.GetType().FullName}.");
            }
            return isRetryable;
        }

Expected behavior

No response

Identity provider

Microsoft Entra ID (Work and School accounts and Personal Microsoft accounts)

Regression

No response

Solution and workarounds

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions