Adding Azure Active Directory Authentication to Android Xamarin.Forms Project

In my previous post I covered adding authentication to the Xamarin Forms Windows Phone 8.0 project. Next step, add it to the Android project. I figured this would be much simpler. However after adding a reference to ADAL from NuGet my Android project failed to build with some esoteric error about some missing layout xml in a referenced component. A quick internet search later I figured it might be due to the path lengths of my projects. I’d been relatively descriptive in my project names (eg RealEstateInspector.XForms.Droid) which had resulted in some very long paths, particularly during the build process where components are added based on the compilation path, the referenced library path and of course the file name. The upshot was that I needed to shorten not the project names, just the physical paths of the projects (easily done via VSO and Source Control Explorer within VS).

After doing the path restructure, I then amended the login the MainActivity:

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

    global::Xamarin.Forms.Forms.Init(this, bundle);
    RealEstateInspector.XForms.MainPage.AuthenticateRequested += Authenticate;
    LoadApplication(new App());
}

public async void Authenticate(object sender, EventArgs e)
{
    var page = sender as RealEstateInspector.XForms.MainPage;
    var token = await AuthenticationHelper.Authenticate(this);
    Debug.WriteLine(token);
    (page.BindingContext as MainViewModel).LoadPropertyData(token);
}

You’ll notice that the activity is passed into the Authenticate method, which means I’ve had to make some minor changes to the AuthenticationHelper code:

public static async Task<string> Authenticate(
#if DROID
    Activity callerActivity
#endif
    )
{
    try
    {
        var authContext = new AuthenticationContext(Constants.ADAuthority);
#if !SILVERLIGHT
        if (authContext.TokenCache.ReadItems().Count() > 0)
            authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
#endif
        var authResult =
            await
                authContext.AcquireTokenAsync(Constants.MobileServiceAppIdUri,
                Constants.ADNativeClientApplicationClientId,
                new Uri(Constants.ADRedirectUri),
#if WINDOWS_PHONE_APP || SILVERLIGHT
                new AuthorizationParameters()
#elif DROID
new AuthorizationParameters(callerActivity)
#else
                    new AuthorizationParameters(PromptBehavior.Auto, false)
#endif
                );
        Debug.WriteLine(authResult != null);

        return authResult.AccessToken;

    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message);
        return null;
    }
}

At this point I also ran into an issue using my dummy redirect uri of http://tba.com, which is actually a real website and has an alternative mobile site which they redirect to. The issue was that after the user had authenticated the web view would redirect to http://tba.com but would then be redirected to the mobile site. I switched to using http://builttoroam.com which I know doesn’t have a redirect. Don’t forget when doing this you also have to update the redirect uri in the Native application in Azure Active Directory.

Leave a comment