Skip to content

Error Handling

Daniel Dobalian edited this page Jan 23, 2019 · 13 revisions

Error Handling in MSAL

After doing a basic integration of MSAL into your app, the next step is to build a great UX around the sign-in experience. One of the key components to a great sign-in experience is properly handling errors. This article gives an overview of the different types of errors developers should look out for and recommends some key actions an app can do in response.

This doc will be evolving over time. If there's an error you'd like to know more about or need a recommendation on, please create a Github issue with the error and question!

Basics

During the silent or interactive MSAL requests, apps may encounter errors generated by various components of the sign-in experience including Consent, Conditional Access (MFA, Device Management, Location-based restrictions), Token issuance and redemption, and user properties.

Some of these errors will require additional error handling on the application side. Currently, there are 2 errors that should be considered:

  • MSALErrorInteractionRequired: The user must perform an interactive request. This can be caused by a multitude of reasons including expired auth session or additional auth requirements.
  • MSALErrorServerDeclinedScopes: The request was not fully completed and some scopes were not granted access to. This can be caused by a user declining consent on certain scopes.

The complete list of all errors can be found at MSALError.h.

Handling Errors

In order to handle the errors above, the following sample code demonstrates the best practice in handling these conditions:

MSALAccount *account = ...;
NSArray<NSString *> *scopes = ...;
MSALPublicClientApplication *application = ...;


MSALCompletionBlock completionBlock;
__block __weak MSALCompletionBlock weakCompletionBlock;

weakCompletionBlock = completionBlock = ^(MSALResult *result, NSError *error)
{
    if (!error)
    {
        // Use result.accessToken
        NSLog(@"accessToken: %@", result.accessToken);
    }
    else
    {
        if ([error.domain isEqualToString:MSALErrorDomain] && error.code == MSALErrorInteractionRequired)
        {
            // Interactive auth will be required
            [application acquireTokenForScopes:scopes
                                       account:account
                               completionBlock:weakCompletionBlock];
        }
        
        if ([error.domain isEqualToString:MSALErrorDomain] && error.code == MSALErrorServerDeclinedScopes)
        {
            // Acquire token silently with available scopes.
            NSArray *grantedScopes = error.userInfo[MSALGrantedScopesKey];
            NSArray *declinedScopes = error.userInfo[MSALDeclinedScopesKey];
            
            NSLog(@"The following scopes were declined: %@", declinedScopes);
            NSLog(@"Trying to acquire a token with granted scopes: %@", grantedScopes);
            
            if (grantedScopes.count > 0)
            {
                [application acquireTokenSilentForScopes:grantedScopes
                                                 account:account
                                         completionBlock:weakCompletionBlock];
            }
            else
            {
                // All scopes were declined.
                NSLog(@"Failed with error %@", error);
            }
        }
        
        // Handle no internet connection.
        if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorNotConnectedToInternet)
        {
            NSLog(@"No internet connection.");
        }
        
        // Other errors may require trying again later, or reporting authentication problems to the user.
        NSLog(@"Failed with error %@", error);
    }
};

// Acquire token silently
[application acquireTokenSilentForScopes:scopes
                                 account:account
                         completionBlock:completionBlock];

// or acquire it interactively.
[application acquireTokenForScopes:scopes
                           account:account
                   completionBlock:completionBlock];

Getting started with MSAL SDK

Configure, Build, Test, Deploy

Advanced Topics

Getting Help, Common Issues, and FAQ

Migrating

News

Clone this wiki locally