Tutorial: Support web fallback

Applies to: Green circle with a white check mark symbol. iOS (Swift) Green circle with a white check mark symbol. macOS (Swift)

This tutorial demonstrates how to acquire a token through a browser where native authentication isn't sufficient to complete the user flow.

In this tutorial, you learn how to:

  • Check BrowserRequired error.
  • Handle BrowserRequired error.

Prerequisites

Browser required

BrowserRequired is a fallback mechanism for various scenarios where native authentication isn't sufficient to complete the user flow.

To ensure stability of your application and avoid interruption of the authentication flow, it's highly recommended to use the SDK's acquireToken() method to continue the flow in the browser.

When we initialize the SDK, we need to specify which challenge types our application can support. Here are the list of challenge types that the SDK accepts:

  • OOB (out of band): add this challenge type when your iOS/macOS application can handle a one-time-passcode, in this case an email code.
  • Password: add this challenge type when your application is able to handle password based authentication.

When Microsoft Entra requires capabilities that the client can't provide the BrowserRequired error will be returned. For example, suppose we initialize the SDK instance specifying only the challenge type OOB, but in Microsoft Entra admin center, the application is configured with an Email with password user flow. When we call the signUp(username) method from the SDK instance, we get a BrowserRequired error, because Microsoft Entra requires different challenge type (password in this case) than the one configured in the SDK.

Insufficient challenge type is only one example of when BrowserRequired can occur. BrowserRequired is a general fallback mechanism that can happen in various scenarios.

Sample flow

In the following code snippet you can see how you can specify the challenge types during the SDK instance initialization:

nativeAuth = try MSALNativeAuthPublicClientApplication(
    clientId: "<client id>",
    tenantSubdomain: "<tenant subdomain>",
    challengeTypes: [.OOB]
)

In this case we're specifying only the challenge type OOB. Suppose that in the Microsoft Entra admin center, the application is configured with an Email with password user flow.

nativeAuth.signUp(username: email, delegate: self)

func onSignUpStartError(error: MSAL.SignUpStartError) {
    if error.isBrowserRequired {
        // handle browser required error
    }
}

When we call the signUp(username:delegate) method from the SDK instance, we get a BrowserRequired error, because Microsoft Entra requires a different challenge type (password in this case) than the one configured in the SDK.

Handle BrowserRequired error

To handle this kind of error, we need to launch a browser and let the user perform the authentication flow there. This can be done by calling acquireToken() method. In order to use this method, a few additional configurations need to be done:

Now we can get a token and an account interactively. Here's an example of how to do it:

func onSignUpStartError(error: MSAL.SignUpStartError) {
    if error.isBrowserRequired {
        let webviewParams = MSALWebviewParameters(authPresentationViewController: self)
        let parameters = MSALInteractiveTokenParameters(scopes: ["User.Read"], webviewParameters: webviewParams)

        nativeAuth.acquireToken(with: parameters) { (result: MSALResult?, error: Error?) in
            // result will contain account and tokens retrieved in the browser
        }
    }
}

The tokens and account that are returned are identical to the ones that would be retrieved through a native auth flow.