Xamarin Forms and the Active Directory Authentication Library (ADAL)

We just finished working on a proof of concept for a project that needed to do Active Directory authentication, primarily using Azure AD. We wanted to do this in Xamarin Forms as the app falls into the realm of a typical line of business UI app and will have a pretty straightforward design.

We started off with some great sample code from the ADAL project team. They have a beta release that supports traditional Xamarin projects (native UI) for Android and iOS as well as Windows Phone. It looked really simple and had great conveniences like async/await support. We thought it would be a walk in the park, not so.

It turns out that the beta version with Xamarin support does not support targeting Silverlight based Windows Phone assemblies. This is important, because Xamarin Forms support for Windows Phone uses the Silverlight implementations. This precluded us from including the authentication login inside the common PCL project. After a little digging it turns out that the ADAL just recently (Jan 15) released a new stable version that introduced support for Silverlight based Windows Phone apps. This was exciting, but there was no complete sample solution and the blog post announcing was missing a couple helpful nuggets of information in the code snippets.

We ended up getting it working, but not as elegantly as we had hoped. By the time I was done I understood a bit more why the original library didn’t handle Silverlight projects, it is a bit more bulky to work with for this situation.

This code is part of a client’s project so there is no sample available right now, we’ll work on getting a stripped down set of code for reference, until then here are some notes on the relevant code changes we made.

Changes for the Windows Phone Project

interface IWebAuthenticationContinuable
{
    /// <summary>
    /// This method is invoked when the web authentication broker returns
    /// with the authentication result
    /// </summary>
    /// <param name="args">Activated event args object that contains returned authentication token</param>
    void ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args);
}
//Changes to make to your Windows Phone App (not Xamarin Forms App)
public partial class App : Application
{
    public App()
    {        
        PhoneApplicationService.Current.ContractActivated += Application_ContractActivated;
    }
    
    private void Application_ContractActivated(object sender, Windows.ApplicationModel.Activation.IActivatedEventArgs e)
    {
        var webAuthenticationBrokerContinuationEventArgs = e as WebAuthenticationBrokerContinuationEventArgs;
        if (webAuthenticationBrokerContinuationEventArgs != null)
        {
            var wabPage = RootFrame.Content as IWebAuthenticationContinuable;
            if (wabPage != null)
            {
                wabPage.ContinueWebAuthentication(webAuthenticationBrokerContinuationEventArgs);
            }
        }
    }
}
//The Root Page of your WP Project
public partial class MainPage : FormsApplicationPage, IWebAuthenticationContinuable
{
    public static AuthenticationContext AuthContext { get; private set; }
    public static Action<string> TheCallback { get; set; }

    public static async void CreateAuthContext(string authUrl)
    {
        AuthContext = await AuthenticationContext.CreateAsync(authUrl, true, new TokenCache());
    }
    
    public async void ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args)
    {
        await AuthContext.ContinueAcquireTokenAsync(args);
    }
}
//Service defined and called from ViewModel, passes in the method to callback.
public class WindowsPhoneAuthorizationService : IAuthorizationService
{
    public void GetAuthorizationToken(string oAuthUrl, string site, Action<string> callbackAction)
    {
        string clientId = "YOUR CLIENT ID"; 
        Uri returnUri = new Uri("YOUR RETURN URI"); 

        MainPage.TheCallback = callbackAction;
        try
        {
            MainPage.CreateAuthContext(oAuthUrl);

            var authContext = MainPage.AuthContext; 
            if (authContext.TokenCache.ReadItems().Count() > 0)
                authContext = AuthenticationContext.CreateAsync(authContext.TokenCache.ReadItems().First().Authority).GetResults();

            authContext.AcquireTokenAndContinue(site, clientId, returnUri, MainPage.callback);
        }
        catch (Exception ee)
        {
            callbackAction(string.Empty);
        }
    }
}

Usage from the ViewModel

//Ueed in my ConnectCommand
private async void ConnectExecute(object param)
{

    var authService = DependencyService.Get<IAuthorizationService>();

    authService.GetAuthorizationToken(oAuthUrl, SiteUrl, setToken); 

}

//callback from authentication
private void setToken(string token)
{
    if (!string.IsNullOrWhiteSpace(token))
    {
        Device.BeginInvokeOnMainThread(() =>
        {
            //Do something with the token.
        });
    }
}

Maybe Xamarin will make some changes that allows them to target Windows Runtime based projects in the future and this will all be irrelevant, but until then hopefully this bit of code helps you make some progress doing Active Directory Authentication in your Xamarin Forms projects.

Update: It looks like last week there was a refresh to the ADAL v3 Preview, but as stated “This refresh does not work with Xamarin.Forms. We are looking into it – and if you have feedback please send it our way! – but we didn’t do work in this refresh to that end.” Good news that they are investigating integrating support. Until then Xamarin Forms and ADAL will continue to be bleeding edge.