I have the following client code to fetch a token from Azure B2C endpoint:
public static async Task<AuthenticationResult> AcquireTokenAsync(this IPublicClientApplication publicClientApp)
{
try
{
var accounts = await publicClientApp.GetAccountsAsync();
return await Task.Run(() =>
publicClientApp
.AcquireTokenInteractive(apiScopes)
.WithAccount(accounts.FirstOrDefault())
.WithPrompt(Prompt.ForceLogin)
.ExecuteAsync());
}
catch (MsalClientException ex)
{
if (ex.ErrorCode.Equals("authentication_canceled"))
{
log.Info("Authentication was cancelled");
}
log.Error("Error in login sequence", ex);
throw;
}
}
Where publicClientApp
is created as such:
app = PublicClientApplicationBuilder.Create(ClientId)
.WithB2CAuthority(Authority)
.Build();
I would like to be able to distinguish different "error code" situations, taking into account MFA. So far I have been able to capture when user cancels/closes the authentication window – which throws MsalClientException with an error code authentication_canceled
.
Next I would like to capture the failed MFA verification, and by debugging the code I can see that after failing the verification enough times, the AcquireTokenInteractive throws:
Microsoft.Identity.Client.MsalClientException:
The browser based authentication dialog failed to complete. Reason: The server encountered an unexpected condition that prevented it from fulfilling the request.
With an error code: authentication_ui_failed
Stack trace:
at Microsoft.Identity.Client.Platforms.net45.WebUI.<AcquireAuthorizationAsync>d__20.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.InteractiveRequest.<AcquireAuthorizationAsync>d__10.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.InteractiveRequest.<ExecuteAsync>d__9.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d__14.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.ApiConfig.Executors.PublicClientExecutor.<ExecuteAsync>d__2.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at MyProject.AzureB2CIntegration.PublicClientApplicationExtensions.<AcquireTokenAsync>d__4.MoveNext() in C:ProjectsMyCommonAzureB2CIntegrationPublicClientApplicationExtensions.cs:line 23
However, when inspecting the traffic on Fiddler, I get a more sensible error response from B2C:
status=500 Internal Server Error
error=server_error
error_description=AADB2C90151: User has exceeded the maximum number for retries for multi-factor authentication.
Question – is there a way to get a more detailed error information (like the one from Fiddler) from an exception that is thrown by AcquireTokenInteractive in such case?
2
Answers
Thank you all for great suggestions - I finally got it working. Turns out behind the scenes I was using a Microsoft.Identity.Client 4.1.0 (due to it being wrapped around by another nuget, dohh). Once that got replaced with the most recent one, things started clicking as I expected.
I created an Azure AD B2C application and added redirect URL like below:
Enabled mobile and desktop flows:
Enable MFA in the user flow:
When I ran the WPF application, I got the sign in screen like below:
The user redirected to MFA prompt:
After sign-in the tokens are generated and you can call the API using the token:
You can find the complete project in my Gitrepo Rukmini3394/WPFApp (github.com)
Reference:
Azure B2C MFA Query – Microsoft Q&A by Givary-MSFT