3

We have Xamarin forms app integrated with azure authentication using MSAL. When we log out we are removing the accounts from the PCA and the code was executed without having any issue. But on the subsequent login, it is getting authenticated without even entering the credentials. It is logging in with previously entered credentials. Looks like the cache is not getting cleared properly.

Showing as "Signed in" on subsequent login and not asking for credentials

private async void AuthenticateUser()
{

    App.Scopes = new string[] { "<client_id>" + "/.default" };
    var redirectUri = "msal<clientId>" + "://auth";
    if (Device.RuntimePlatform == Device.iOS)
    {
        App.PCA = PublicClientApplicationBuilder.Create("<client_id>")
                    .WithIosKeychainSecurityGroup("<package_name>")
                    .WithRedirectUri(redirectUri)
                    .Build();
    }
    else
    {
        App.PCA = PublicClientApplicationBuilder
            .Create(CommonHelper.ClientId)
            .WithRedirectUri(redirectUri)
            .Build();
    }

    var accounts = await App.PCA.GetAccountsAsync();
    var uid = new UserIdentifier("<user_name>", UserIdentifierType.OptionalDisplayableId);
    AuthenticationResult authResult;
    try
    {
        while (accounts.Any())
        {
            await App.PCA.RemoveAsync(accounts.First());
            accounts = (await App.PCA.GetAccountsAsync()).ToList();
        }
        var firstAccount = accounts.FirstOrDefault();
        authResult = await App.PCA.AcquireTokenSilent(App.Scopes, firstAccount)
                              .ExecuteAsync();
        
        ProceedToLogin(authResult.AccessToken);
    }
    catch (MsalUiRequiredException mex)
    {
        try
        {
            authResult = await App.PCA.AcquireTokenInteractive(App.Scopes)
                                      .WithParentActivityOrWindow(App.ParentWindow)
                                      .WithLoginHint("<user_name>")
                                      .WithUseEmbeddedWebView(true)
                                      .ExecuteAsync();
            
            ProceedToLogin(authResult.AccessToken);
        }
        catch (Exception ex)
        {
            Log(ex);
        }
    }

}

Please find the code below which will execute during the logout.

        public void Logout(string authority)
        {
            if (App.PCA == null)
                {
                    App.Scopes = new string[] { "<client_id>" + "/.default" };
                    var redirectUri = "msal<azure_client_id>://auth";
                    App.PCA = PublicClientApplicationBuilder.Create("<client_id>")
                                .WithIosKeychainSecurityGroup("<package_name>")
                                .WithRedirectUri(redirectUri)
                                .Build();
                }
                var accounts = App.PCA.GetAccountsAsync().Result;
                if (accounts != null)
                {
                    while (accounts.Any())
                    {
                        App.PCA.RemoveAsync(accounts.First());
                        accounts = App.PCA.GetAccountsAsync().Result;
                    }
                }
        }

Also, we tried with the below code to clear the cookies. It was working fine in lower versions but again the issue is happening from iOS 14.6 and above.

var cookieStorage = NSHttpCookieStorage.SharedStorage;
foreach (var cookie in cookieStorage.Cookies)
{
   cookieStorage.DeleteCookie(cookie);
}
Ramesh Annadurai
  • 356
  • 1
  • 10

2 Answers2

1

As far as I understand this from my own implementation of MSAL in .NET this is working as expected, I'm not sure how well this carries over to Xamarin. When you log a user out of they will no longer be authenticated against your application, but will keep authentication to Microsoft. When you send an unauthenticated user to the Microsoft endpoint to log back in to your application (as in your screenshot) Microsoft correctly identifies that they are still logged in to their Microsoft account, however that account is not logged in to your application. At this point Microsoft offers the list you see giving the option to use the authenticated account or choose a different one to use sign in to your application.

Their are two levels in play when authenticating against MS, authentication against MS and authentication against your application. Your application can only clear authentication against itself, not Microsoft which lets user stay logged into to other MS services (Outlook etc).

JustAnotherDev
  • 546
  • 2
  • 8
1

Try adding the following line

.WithPrompt(Prompt.ForceLogin);

Example

PublicClientApplicationBuilder.Create("<client_id>")
                .WithIosKeychainSecurityGroup("<package_name>")
                .WithRedirectUri(redirectUri)
                .WithPrompt(Prompt.ForceLogin);
                .Build();