0
votes

I'm trying to use AD B2C with my Mobile App using Xamarin.Android, but not Forms.

All examples on how to use AD B2C with Xamarin are using the MSAL, which seems to rely on using Xamarin.Forms. I was not able to find an example or documentation on how to integrate it into Xamarin.Android.

Examples I was able to find but did not meet my needs:
https://github.com/Azure-Samples/active-directory-android-native-appauth-b2c
https://github.com/Azure-Samples/active-directory-b2c-xamarin-native

Documentation I read and tried to apply, but did not result in a succesful authentication or where not applicable to my situation:
https://developer.xamarin.com/guides/xamarin-forms/cloud-services/authentication/azure/
https://developer.xamarin.com/guides/xamarin-forms/cloud-services/authentication/azure-ad-b2c/
https://developer.xamarin.com/guides/xamarin-forms/cloud-services/authentication/azure-ad-b2c-mobile-app/

Is there a way to use MSAL in Xamarin.Android without using Forms or do I have to use some other library like AppAuth?

UPDATE: How I tried to use MSAL:

public static string ClientId = "MyClientId";
public static string SignUpSignInPolicy = "B2C_1_MyPolicyName";
public static string Authority = "My Authority";
public static string[] Scopes = { ClientId };


private AuthenticationManager()
{
    AuthenticationClient = new PublicClientApplication(ClientId, Authority);
}
    public async Task<AuthenticationResult> AuthenticateAsync()
{
    if (!Initialized)
        throw new InvalidOperationException("Cannot authenticate before AuthenticationManager has been initialized.");

    AuthResult = await AuthenticationClient.AcquireTokenAsync(Scopes,
                                        "",
                                        UiOptions.SelectAccount,
                                        string.Empty,
                                        null,
                                        Authority,
                                        SignUpSignInPolicy);
    return AuthResult;
}
public void Initialize(Activity activity)
{
    if (Initialized)
        return;
    // Load shared prefrences (skipped)
    AuthenticationClient.PlatformParameters = new PlatformParameters(activity);
    Initialized = true;
}

In the call for AquireTokenAsync(..), this results in NullPointerException:
"Value cannot be null. Parameter name: clientId"
I'm using the same parameters as in the examples (and they don't crash), everything should be initialized. One reason for this error could be that the parameters for AquireTokenAsync(..) are different when calling it from android. (Please see the source of PublicClientApplication and look for the precompiler directives.)
But if that's the case I don't really know how to build the project with, so that the correct version for android is selected.

UPDATE2: Added code from activity which should launch the authentication process:

public class LoginActivity : Activity
{
    private async void LoginButtonClicked()
    {
        try
        {
            AuthenticationManager.AuthManager.Initialize(this);
            await AuthenticationManager.AuthManager.AuthenticateAsync();
        }
        // Create your application here
        catch (Exception e)
        {
            CreateAndShowDialog(e, Resources.GetString(Resource.String.error_sync));
        }
    }

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        base.OnActivityResult(requestCode, resultCode, data);
        AuthenticationAgentContinuationHelper.SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode, data);
    }
2
please add some code from one of your attempts - brennan
@bren added code and my what what I suspect to be a reason why my application crashes. I ommitted it first because I thought I the answer will be, that I have to use something different to MSAL. I don't really understand how it is able to launch a WebView and all that within Xamarin.Android without Xamarin.Forms - A. Yurikov
I found out that indeed the value of ClientId is null dispite it being set on compiletime. Maybe I have to refer to AuthenticationManager.ClientId. This is a behaviour I did not expect (coming from Java-World). I will try this tomorrow. If that resolves my problem I will post this as a solution. - A. Yurikov

2 Answers

0
votes

Do you have this in your MainActivity.cs?

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);   
    AuthenticationAgentContinuationHelper
        .SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode, data);
}
0
votes

This is old. But if anyone has the same problem it's highly unlikely that he did the same stupid error as I did:

Field members are initialized in order.

There was some dependency between my field members and due to wrong order one value evaluated to null when initializing the dependent part.