|
| 1 | +--- |
| 2 | +title: Handle errors and exceptions in MSAL.js |
| 3 | +description: Learn how to handle errors and exceptions, Conditional Access claims challenges, and retries in MSAL.js applications. |
| 4 | +author: Dickson-Mwendia |
| 5 | +manager: CelesteDG |
| 6 | +ms.author: dmwendia |
| 7 | +ms.custom: devx-track-js |
| 8 | +ms.date: 11/26/2020 |
| 9 | +ms.reviewer: saeeda, hahamil |
| 10 | +ms.service: active-directory |
| 11 | +ms.subservice: develop |
| 12 | +ms.topic: conceptual |
| 13 | +#Customer intent: |
| 14 | +--- |
| 15 | +# Handle errors and exceptions in MSAL.js |
| 16 | + |
| 17 | +[!INCLUDE [Active directory error handling introduction](./includes/error-handling-and-tips/error-handling-introduction.md)] |
| 18 | + |
| 19 | +## Error handling in MSAL.js |
| 20 | + |
| 21 | +MSAL.js provides error objects that abstract and classify the different types of common errors. It also provides an interface to access specific details of the errors such as error messages to handle them appropriately. |
| 22 | + |
| 23 | +### Error object |
| 24 | + |
| 25 | +```javascript |
| 26 | +export class AuthError extends Error { |
| 27 | + // This is a short code describing the error |
| 28 | + errorCode: string; |
| 29 | + // This is a descriptive string of the error, |
| 30 | + // and may also contain the mitigation strategy |
| 31 | + errorMessage: string; |
| 32 | + // Name of the error class |
| 33 | + this.name = "AuthError"; |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +By extending the error class, you have access to the following properties: |
| 38 | +- `AuthError.message`: Same as the `errorMessage`. |
| 39 | +- `AuthError.stack`: Stack trace for thrown errors. |
| 40 | + |
| 41 | +### Error types |
| 42 | + |
| 43 | +The following error types are available: |
| 44 | + |
| 45 | +- `AuthError`: Base error class for the MSAL.js library, also used for unexpected errors. |
| 46 | + |
| 47 | +- `ClientAuthError`: Error class which denotes an issue with Client authentication. Most errors that come from the library are ClientAuthErrors. These errors result from things like calling a login method when login is already in progress, the user cancels the login, and so on. |
| 48 | + |
| 49 | +- `ClientConfigurationError`: Error class, extends `ClientAuthError` thrown before requests are made when the given user config parameters are malformed or missing. |
| 50 | + |
| 51 | +- `ServerError`: Error class, represents the error strings sent by the authentication server. These errors may be invalid request formats or parameters, or any other errors that prevent the server from authenticating or authorizing the user. |
| 52 | + |
| 53 | +- `InteractionRequiredAuthError`: Error class, extends `ServerError` to represent server errors, which require an interactive call. This error is thrown by `acquireTokenSilent` if the user is required to interact with the server to provide credentials or consent for authentication/authorization. Error codes include `"interaction_required"`, `"login_required"`, and `"consent_required"`. |
| 54 | + |
| 55 | +For error handling in authentication flows with redirect methods (`loginRedirect`, `acquireTokenRedirect`), you'll need to handle the redirect promise, which is called with success or failure after the redirect using the `handleRedirectPromise()` method as follows: |
| 56 | + |
| 57 | +```javascript |
| 58 | +const msal = require('@azure/msal-browser'); |
| 59 | +const myMSALObj = new msal.PublicClientApplication(msalConfig); |
| 60 | + |
| 61 | +// Register Callbacks for redirect flow |
| 62 | +myMSALObj.handleRedirectPromise() |
| 63 | + .then(function (response) { |
| 64 | + //success response |
| 65 | + }) |
| 66 | + .catch((error) => { |
| 67 | + console.log(error); |
| 68 | + }) |
| 69 | +myMSALObj.acquireTokenRedirect(request); |
| 70 | +``` |
| 71 | + |
| 72 | +The methods for pop-up experience (`loginPopup`, `acquireTokenPopup`) return promises, so you can use the promise pattern (`.then` and `.catch`) to handle them as shown: |
| 73 | + |
| 74 | +```javascript |
| 75 | +myMSALObj.acquireTokenPopup(request).then( |
| 76 | + function (response) { |
| 77 | + // success response |
| 78 | + }).catch(function (error) { |
| 79 | + console.log(error); |
| 80 | + }); |
| 81 | +``` |
| 82 | + |
| 83 | +### Errors that require interaction |
| 84 | + |
| 85 | +An error is returned when you attempt to use a non-interactive method of acquiring a token such as `acquireTokenSilent`, but MSAL couldn't do it silently. |
| 86 | + |
| 87 | +Possible reasons are: |
| 88 | + |
| 89 | +- you need to sign in |
| 90 | +- you need to consent |
| 91 | +- you need to go through a multi-factor authentication experience. |
| 92 | + |
| 93 | +The remediation is to call an interactive method such as `acquireTokenPopup` or `acquireTokenRedirect`: |
| 94 | + |
| 95 | +```javascript |
| 96 | +// Request for Access Token |
| 97 | +myMSALObj.acquireTokenSilent(request).then(function (response) { |
| 98 | + // call API |
| 99 | +}).catch( function (error) { |
| 100 | + // call acquireTokenPopup in case of acquireTokenSilent failure |
| 101 | + // due to interaction required |
| 102 | + if (error instanceof InteractionRequiredAuthError) { |
| 103 | + myMSALObj.acquireTokenPopup(request).then( |
| 104 | + function (response) { |
| 105 | + // call API |
| 106 | + }).catch(function (error) { |
| 107 | + console.log(error); |
| 108 | + }); |
| 109 | + } |
| 110 | +}); |
| 111 | +``` |
| 112 | + |
| 113 | +[!INCLUDE [Active directory error handling claims challenges](./includes/error-handling-and-tips/error-handling-claims-challenges.md)] |
| 114 | + |
| 115 | +When getting tokens silently (using `acquireTokenSilent`) using MSAL.js, your application may receive errors when a [Conditional Access claims challenge](v2-conditional-access-dev-guide.md) such as MFA policy is required by an API you're trying to access. |
| 116 | + |
| 117 | +The pattern to handle this error is to make an interactive call to acquire token in MSAL.js such as `acquireTokenPopup` or `acquireTokenRedirect` as in the following example: |
| 118 | + |
| 119 | +```javascript |
| 120 | +myMSALObj.acquireTokenSilent(accessTokenRequest).then(function(accessTokenResponse) { |
| 121 | + // call API |
| 122 | +}).catch(function(error) { |
| 123 | + if (error instanceof InteractionRequiredAuthError) { |
| 124 | + |
| 125 | + // extract, if exists, claims from the error object |
| 126 | + if (error.claims) { |
| 127 | + accessTokenRequest.claims = error.claims, |
| 128 | + |
| 129 | + // call acquireTokenPopup in case of InteractionRequiredAuthError failure |
| 130 | + myMSALObj.acquireTokenPopup(accessTokenRequest).then(function(accessTokenResponse) { |
| 131 | + // call API |
| 132 | + }).catch(function(error) { |
| 133 | + console.log(error); |
| 134 | + }); |
| 135 | + } |
| 136 | +}); |
| 137 | +``` |
| 138 | +
|
| 139 | +Interactively acquiring the token prompts the user and gives them the opportunity to satisfy the required Conditional Access policy. |
| 140 | +
|
| 141 | +When calling an API requiring Conditional Access, you can receive a claims challenge in the error from the API. In this case, you can pass the claims returned in the error to the `claims` parameter in the [access token request object](msal-js-pass-custom-state-authentication-request.md) to satisfy the appropriate policy. |
| 142 | +
|
| 143 | +See [How to use Continuous Access Evaluation enabled APIs in your applications](./app-resilience-continuous-access-evaluation.md) for more detail. |
| 144 | +
|
| 145 | +### Using other frameworks |
| 146 | +
|
| 147 | +Using toolkits like Tauri for registered single page applications (SPAs) with the identity platform are not recognized for production apps. SPAs only support URLs that start with `https` for production apps and `http://localhost` for local development. Prefixes like `tauri://localhost` cannot be used for browser apps. This format can only be supported for mobile or web apps as they have a confidential component unlike browser apps. |
| 148 | + |
| 149 | +[!INCLUDE [Active directory error handling retries](./includes/error-handling-and-tips/error-handling-retries.md)] |
| 150 | + |
| 151 | +## Next steps |
| 152 | + |
| 153 | +Consider enabling [Logging in MSAL.js](msal-logging-js.md) to help you diagnose and debug issues |
0 commit comments