Skip to content

MsalUiRequiredException classification

Bogdan Gavril edited this page Jun 27, 2019 · 8 revisions

Note: Feature available from: 4.1

Understanding MsalUiRequiredException

One of common status codes returned from MSAL.NET when calling AcquireTokenSilent() is MsalError.InvalidGrantError. This status code means that the application should call the authentication library again, but in interactive mode (AcquireTokenInteractive or AcquireTokenByDeviceCodeFlow for public client applications, and do a challenge in Web apps). This is because additional user interaction is required before authentication token can be issued.

Most of the time when AcquireTokenSilent fails, it is because the token cache does not have tokens matching your request. Access tokens expire in 1h, and AcquireTokenSilent will try to fetch a new one based on a refresh token (in OAuth2 terms, this is the "Refresh Token' flow). This flow can also fail for various reasons, for example if a tenant admin configures more stringent login policies.

The interaction aims at having the user do an action. Some of those conditions are easy for users to resolve (e.g. accept Terms of Use with a single click), and some cannot be resolved with the current configuration (e.g. the machine in question needs to connect to a specific corporate network). Some help the user setting-up Multi-factor authentication, or install Microsoft Authenticator on their device.

MsalUiRequiredException Classification

MSAL exposes a Classification field, which you can read to provide a better user experience, for example to tell the user that his password expired or that he will need to provide consent to use some resources. The supported values are:

Classification Meaning Recommended handling
basic_action Condition can be resolved by user interaction during the interactive authentication flow. Call AcquireTokenInteractively().
additional_action Condition can be resolved by additional remedial interaction with the system, outside of the interactive authentication flow. Call AcquireTokenInteractively() to show a message that explains the remedial action. Calling application may choose to hide flows that require additional_action if the user is unlikely to complete the remedial action.
message_only Condition cannot be resolved at this time. Launching interactive authentication flow will show a message explaining the condition. Call AcquireTokenInteractively() to show a message that explains the condition. AcquireTokenInteractively() will return UserCanceled error after the user reads the message and closes the window. Calling application may choose to hide flows that result in message_only if the user is unlikely to benefit from the message.
consent_required User consent is missing, or has been revoked. Call AcquireTokenInteractively() for user to give consent.
user_password_expired User's password has expired. Call AcquireTokenInteractively() so that user can reset their password.
[empty string] Condition may be resolved by user interaction during the interactive authentication flow. Call AcquireTokenInteractively().

Code Example

AuthenticationResult res;
try
{
    res = await application.AcquireTokenSilent(scopes, account)
                           .ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
    switch (ex.Classification)
    {
        case MsalUiRequiredException.MessageOnly:
            // You might want to call AcquireTokenInteractive() to show a message that explains the condition. 
            // AcquireTokenInteractive() will return UserCanceled error after the user reads the message 
            // and closes the window. 
            // Calling application may choose to hide flows that result in message_only if the user is unlikely to benefit from the message
            try
            {
                res = await application.AcquireTokenInteractive(scopes)
                                       .ExecuteAsync();
            }
            catch (MsalClientException ex2) when (ex2.ErrorCode == MsalError.AuthenticationCanceledError)
            {
                // Do nothing. The user has seen the message
            }
            break;

        case MsalUiRequiredException.AdditionalAction:
        // You might want to call AcquireTokenInteractive() to show a message that explains the remedial action. 
        // The calling application may choose to hide flows that require additional_action if the user 
        // is unlikely to complete the remedial action (even if this means a degraded experience)

        case MsalUiRequiredException.BasicAction:
        // Call AcquireTokenInteractive()

        case MsalUiRequiredException.ConsentRequired:
        // Call AcquireTokenInteractive() for user to give consent.

        case MsalUiRequiredException.UserPasswordExpired:
        // Call AcquireTokenInteractive() so that user can reset their password

        case "":
            // Condition may be resolved by user interaction during the interactive authentication flow.

            res = await application.AcquireTokenInteractive(scopes)
                                                           .ExecuteAsync();
            break;

        default:
            break;
    }
}

For full details see Issue #1148

Getting started with MSAL.NET

Acquiring tokens

Desktop/Mobile apps

Web Apps / Web APIs / daemon apps

Advanced topics

News

FAQ

Other resources

Clone this wiki locally