title: Weird login behaviour using Azure AD B2C with Xamarin iOS
body: <p>We have a <strong>Xamarin Forms</strong> app that uses <strong>Azure AD B2C</strong> for login. I have followed this example code <a href="https://github.com/Azure-Samples/active-directory-b2c-xamarin-native" rel="nofollow noreferrer">https://github.com/Azure-Samples/active-directory-b2c-xamarin-native</a></p>
  
  <p>The <strong>Android</strong> version works perfectly. The workflow is seamless and works as expected. </p>
  
  <p>On the <strong>iOS</strong> version we are getting some weird behaviour though.</p>
  
  <p>Here is the flow on the <strong>iOS</strong> version of the app. </p>
  
  <ol>
  <li>User launches the app and is presented with the Azure AD B2C login screen <em>(correct)</em></li>
  <li>User enters their credentials <em>(correct)</em></li>
  <li>The app redirects the user back to the login screen (with the username and password fields blank) <em>(wrong)</em></li>
  <li>After a few seconds the app then logs them in and navigates them to the main screen</li>
  </ol>
  
  <p>After entering their credentials the user should be immediately navigated to the app main screen, NOT back to the login screen. </p>
  
  <p>Once they are logged in, subsequently launching the app correctly logs them in. The problem is only on first login.</p>
  
  <p>I can't seem to find any help on this anywhere. Is it the Safari browser, the token cache, something else? The code and workflow are correct as the <strong>Android</strong> version works perfectly, so it's something specific to the iOS app.</p>
  
  <p><strong>UPDATE</strong>
  After some investigation it seems that this method may be causing the issue.</p>
  
  <pre><code>public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
  {
    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
    return true;
  }
  </code></pre>
  
  <p>According to the docs</p>
  
  <blockquote>
    <p>this logic is meant to ensure that once the interactive portion of the
    authentication flow is concluded, the flow goes back to MSAL</p>
  </blockquote>
  
  <p>But it doesn't. It redirects the user back to the <em>OnAppearing</em>() method of the login page where it attempts (again) to acquire a token (which it does).</p>
  
  <p>Is there any way to fix the behaviour of this method?</p>
  
  <pre><code>AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url)
  </code></pre>
  
  <p><strong>UPDATE2</strong>
  Here is the login code (simplified for clarity)</p>
  
  <pre><code>protected override async void OnAppearing()
  {
      base.OnAppearing();
  
      // Check to see if we have a User in the cache already.
      try
      {
          IEnumerable&lt;IAccount&gt; accounts = await AuthenticationService.PCA().GetAccountsAsync();
          var account = this.GetAccountByPolicy(accounts, ApplicationConstants.SignUpSignInPolicy);
          AuthenticationResult ar = await AuthenticationService.PCA().AcquireTokenSilentAsync(ApplicationConstants.Scopes, account, ApplicationConstants.Authority, false);
      }
      catch (Exception)
      {
          // Doesn't matter, we go in interactive mode
          this.OnSignIn();
      }
  }
  
  private async void OnSignIn()
  {
      try
      {
          IEnumerable&lt;IAccount&gt; accounts = await AuthenticationService.PCA().GetAccountsAsync();
          var account = this.GetAccountByPolicy(accounts, ApplicationConstants.SignUpSignInPolicy);
  
          AuthenticationResult ar = await AuthenticationService.PCA().AcquireTokenAsync(ApplicationConstants.Scopes, account, App.UiParent);
      }
      catch (Exception ex)
      {
          InstanceManager.LoggingHelper().TrackError(ex);
          // Checking the exception message
          // should ONLY be done for B2C
          // reset and not any other error.
          if (ex.Message.Contains("AADB2C90118"))
          {
              this.OnPasswordReset();
          }
          else
          {
              await DisplayAlert(StringConstants.ExceptionText, StringConstants.AuthenticationError, StringConstants.CloseDialog);
              this.OnSignIn();
          }
      }
  }
  </code></pre>