Active Directory Authentication in Xamarin.Forms

By Marco Troncone · · 3 min read
Share
First published on xamarinexpert.it in 2019. It was written for Xamarin, which reached end of support in May 2024: the ideas still apply to .NET MAUI, but some APIs and tools have changed.

Many modern apps require a secure authentication for users and Azure Active Directory Authentication Library (ADAL) enables application developers to authenticate users to cloud or on-premises Active Directory (AD). Here I show two different ways to add ADAL to a Xamarin.Forms project.

The short way: MTADAL Plugin

This is a plugin I have created to add ADAL to all my projects and I've decided to make it freely available to everyone.The plugin page here: https://www.hightouchinnovation.com/blog/adal-made-easyA tutorial to use the plugin is here: https://www.hightouchinnovation.com/blog/adal-made-easy

This plugin is really easy to use. You just need to install it in your projects (PCL/.NetStandard and platform projects) and write:

AuthenticationResult data = await MTADAL.Current.Authenticate(Authority, GraphResourceUri, ClientId, ReturnUri);

That's it. Basically in less than a minute you are ready to authenticate your users.

The long way: Write the authentication code

In case you don't want to use the MTADAL plugin, you can write the code by yourself in your projects.The first thing you need to do is install the ADAL nuget package in your projects (https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/)

In our PCL/.NetStanrdard project we need to add this interface:

public interface IAuthenticator
{
    Task<AuthenticationResult> Authenticate(string authority, string resource, string clientId, string returnUri);
    void Logout(string authority);
    bool hasLoginData(string authority);
}

and when we want to authenticate a user we need to use this code:

var auth = DependencyService.Get<IAuthenticator>();
            AuthenticationResult data = await auth.Authenticate(App.Authority, App.GraphResourceUri, App.ClientId, App.ReturnUri);

Before we can authenticate the users, we need to add the code in each of the platform project we need the authentication (eg. Android, iOS, UWP):

Android

Here we need to implement the interface created in our PCL/.NetStandard project.

[assembly: Dependency(typeof(Authenticator))]

namespace YOURNAMESPACE
{
    public class Authenticator : IAuthenticator
    {
        public async Task<AuthenticationResult> Authenticate(string authority, string resource, string clientId, string returnUri)
        {
            try
            {
                var authContext = new AuthenticationContext(authority);
                if (authContext.TokenCache.ReadItems().Any()) 
                    authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
                var uri = new Uri(returnUri);
                var platformParams = new PlatformParameters((Activity) Forms.Context);
                var authResult = await authContext.AcquireTokenAsync(resource, clientId, uri, platformParams);
                return authResult;
            }
            catch (Exception ecc)
            {
                return null;
            }
        }

        public bool hasLoginData(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            return authContext.TokenCache.ReadItems().Any();
        }

        public void Logout(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            if (authContext.TokenCache.ReadItems().Any()) authContext.TokenCache.Clear();
        }
    }
}

We need to register the class with DependencyService otherwise the code will not work. We can register the class adding this line before the namespace:[assembly: Dependency(typeof(Authenticator))]Don't forget it otherwise the authentication will not work!Inside your MainActivity class you also need to add this code:

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

This will intercept the result from the ADAL activity and will allow you to conclude successfully the authentication.

iOS

We need to add the class to our iOS project:

[assembly: Dependency(typeof(Authenticator))]

namespace YOURNAMESPACE
{
    class Authenticator : IAuthenticator
    {
        public async Task<AuthenticationResult> Authenticate(string authority, string resource, string clientId, string returnUri)
        {
            try
            {
                var authContext = new AuthenticationContext(authority);
                if (authContext.TokenCache.ReadItems().Any())
                    authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
                var controller = UIApplication.SharedApplication.KeyWindow.RootViewController;
                var uri = new Uri(returnUri);
                var platformParams = new PlatformParameters(controller);
                var authResult = await authContext.AcquireTokenAsync(resource, clientId, uri, platformParams);
                return authResult;
            }
            catch (Exception ecc)
            {
                return null;
            }
        }

        public bool hasLoginData(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            return authContext.TokenCache.ReadItems().Any();
        }

        public void Logout(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            if (authContext.TokenCache.ReadItems().Any()) authContext.TokenCache.Clear();
        }
    }
}

This class is the only thing you need to authenticate your users on iOS.Again, remember to add the line[assembly: Dependency(typeof(Authenticator))]

UWP

We need to add the class to our UWP project:

[assembly: Dependency(typeof(Authenticator))]

namespace YOURNAMESPACE
{
    public class Authenticator : IAuthenticator
    {
        public async Task<AuthenticationResult> Authenticate(string authority, string resource, string clientId, string returnUri)
        {
            try
            {
                var authContext = new AuthenticationContext(authority);
                if (authContext.TokenCache.ReadItems().Any())
                    authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
                var uri = new Uri(returnUri);
                var platformParams = new PlatformParameters(PromptBehavior.Auto, false);
                var authResult = await authContext.AcquireTokenAsync(resource, clientId, uri, platformParams);
                return authResult;
            }
            catch (Exception ecc)
            {
                return null;
            }
        }

        public void Logout(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            if (authContext.TokenCache.ReadItems().Any()) authContext.TokenCache.Clear();
        }

        public bool hasLoginData(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            return authContext.TokenCache.ReadItems().Any();
        }
    }
}

This class is the only thing you need to authenticate your users on UWP.Again, remember to add the line[assembly: Dependency(typeof(Authenticator))]

Summary

It's incredibly easy to authenticate users in a Xamarin.Forms projects. You can do it in 2 ways:

  1. Use the MTADAL Plugin
  2. Install the ADAL Plugin, add then interface and add the classes above for each of your platform projects!
Share

Need help with your app?

I build and rescue .NET MAUI, Xamarin, Android and iOS apps, and I'm available for contract and consulting work.

Hire me

← All articles