-
Notifications
You must be signed in to change notification settings - Fork 146
Error Handling
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!
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.
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];
- Customizing Browsers and WebViews
- Logging
- Sovereign clouds
- B2C
- Auth Telemetry (coming soon)
- MSAL questions, bugs and issues (coming soon)
- Redirect URIs
- Requesting individual claims
- Keychain cache
- SSL issues
- iOS 13 and macOS 10.15 support
- Releases
- Roadmap (coming soon)