-
Notifications
You must be signed in to change notification settings - Fork 145
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 in MSALError enum.
Note: MSALInternalError
enum exists only for the reference, you should not try to handle these errors in runtime.
In order to handle the errors above, the following sample code demonstrates the best practice in handling these conditions:
MSALInteractiveTokenParameters *interactiveParameters = ...;
MSALSilentTokenParameters *silentParameters = ...;
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 acquireTokenWithParameters:interactiveParameters
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)
{
silentParameters.scopes = grantedScopes;
[application acquireTokenSilentWithParameters:silentParameters
completionBlock:weakCompletionBlock];
}
else
{
// All scopes were declined.
NSLog(@"Failed with error %@", error);
}
}
if ([error.domain isEqualToString:MSALErrorDomain] && error.code == MSALErrorWorkplaceJoinRequired)
{
// You may want to ask the user to work place join the device (open Authenticator app -> Settings -> Device Registration).
// Handling of this error is optional.
}
if ([error.domain isEqualToString:MSALErrorDomain] && error.code == MSALErrorServerProtectionPoliciesRequired)
{
// Integrate the Intune SDK and call the remediateComplianceForIdentity:silent: API.
// Handle this error only if you integrated Intune SDK, see more info here: https://aka.ms/intuneMAMSDK
}
if ([error.domain isEqualToString:MSALErrorDomain] && error.code == MSALErrorUserCanceled)
{
// The user cancelled the web auth session. You may want to ask the user to try again.
// Handling of this error is optional.
}
if ([error.domain isEqualToString:MSALErrorDomain] && error.code == MSALErrorInternal)
{
// Log the error, then inspect the MSALInternalErrorCodeKey in the userInfo dictionary.
// More detailed information about the specific error under MSALInternalErrorCodeKey can be found in MSALInternalError enum.
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 acquireTokenSilentWithParameters:silentParameters
completionBlock:completionBlock];
// or acquire it interactively.
[application acquireTokenWithParameters:interactiveParameters
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)