Since some time I’m involved in creating business applications for multiple platforms. The platforms we target are mostly Windows 10 and iOS. We use Xamarin as a cross-platform development tool because it allows us to create native mobile and desktop applications.

Because we are talking about business applications it would be nice to use authentication based on Azure Active Directory. Currently there is something called ADAL. ADAL stands for Active Directory Authentication Library. It enables client application developers to authenticate users to cloud or on-premises Active Directory. Security access tokens are returned which then can be used to access other resources like the Microsoft Graph, Yammer and other.

This article describes all the necessary steps from begin to end to use ADAL in combination with cross-platform applications. For demo purposes we will retrieve the group names in which the logged on user anticipates. In this article we focus mainly on iOS and Windows 10 (Universal apps). The article contains the following content.

  • Register your application in Azure AD
  • Create the cross-platform Xamarin framework
  • Implement the authentication classes
  • Understand PlatformParameters
  • Create a login page
  • Implement code for getting groups
  • The result

Register your application in Azure AD

Before we can use ADAL we need to register our application in Azure Active Directory. For this you will need sufficient rights to add an application to your companies Azure Active Directory. Go to https://manage.windowsazure.com and login with the correct credentials. Select on the left “Active Directory” and click on the Azure AD which you want to use. In my case there is only one Active Directory called “appzinside”.

Click on the name of the Active Directory and select the tab “APPLICATIONS”. Click on the “ADD” button at the bottom. A wizard dialog is shown which allows you to choose from two options. Select “Add an application my organization is developing”.

Enter a name and choose “Native Client Application” as type.

The next step is to specify a redirect URL. Click on the finish button and your application is created in a few minutes.

When the application is created it will appear under the applications for the selected Azure AD. Click on the application to open it and select the tab “Configuration”.

You will notice that your application has a client id and that it is possible to enter additional redirect URLs. You will need the combination of both to access and authenticate with ADAL against Azure AD. At the moment the application has only one delegated permission for Azure AD itself. The next step is to add delegated permissions for the Microsoft Graph. Click on the “Add application” button.

The following dialog will allow you to select from different applications / resources. In our case we need to have delegated permissions for the Microsoft Graph. Select the Microsoft Graph and press the finish button.

The Microsoft Graph is now added as application / resource to allow you to specify delegated permissions. Select the permissions and do not forget to save your application.

These permissions are important since they need to be approved by the user which is using your application. During the authentication mechanism the user is requested consensus for these permissions. With other words, it asks the user if it is allowed on his/her behalf to use those permissions.

Create the cross-platform Xamarin framework

For our demo we use Visual Studio 2015 with Xamarin platform installed. Make sure that you have Xamarin.Forms version 2.x or higher installed. This allows us also to create cross-platform applications for Windows 10 devices. Also make sure you have a valid license with Xamarin to continue.

Open Visual Studio and select “Blank App (Xamarin.Forms Portable) under “Cross-platform” as a new project. This will create a cross-platform Xamarin project using a portable class library for a set of different platforms.

To make things easier remove all project types you are not going to use. For this demo only three projects will remain. The portable class library, the iOS project and the Universal Windows project. The last one is used for Windows 10 devices. To remove the others just right mouse click on the projects and choose “remove”.

To use ADAL with Xamarin we need have the prelease van ADAL 3.x installed through NuGet packages. Make sure you have the checkbox “Include prelease” checked and search for “Active Directory Authentication Library”. These NuGet packages need to be installed on the portable class library project and the iOS project. There is no need to install it on the Universal Windows project.

Implement the authentication classes

Let’s start coding. There are different approaches possible. Vittorio Bertocci describes in his blogpost a pattern called “PageRenderer/IPlatformParameter”. PageRenderer allows us to add additional functionality through subclassing. He defines a single class in the portable class library and uses this technique to set the PlatformParameter per platform.

Mayur Tendulkar has created a post in which he uses a different approach by using implementation classes per platform. In this case an interface is defined. This interface is implemented per platform.

While both patterns are great, I still like to suggest a third alternative which is a variant on the pattern of Mayur Tandulkar. As programmer I try to write code which is easy to maintain. That means optimizes it so that only one class is handling the functionality. In this case authenticating against Azure AD through ADAL.

So the following code is the same as in his post and defines an interface for the authentication. The Authenticate method returns a friendlier result code. This class is stored in the portable class library.

using System.Threading.Tasks;

namespace ADALXamarinExample

{

public interface IADALAuthenticator

{

Task<AuthenticationResultCode> Authenticate(string resource, string clientId, string returnUri);

}

}

Secondly I created another class which handles the authentication functionality. This class is also part of the portable class library. This class is based on the singleton pattern. This makes sure that there is only one instance of the class present containing the results like error messages and the access token. You can use the class from any place by calling ADALAuthentication.Instance.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Microsoft.IdentityModel.Clients.ActiveDirectory;

using Xamarin.Forms;

namespace ADALXamarinExample

{

public enum AuthenticationResultCode

{

Succesfull,

Canceled,

Denied,

Unknown,

None

}

public class ADALAuthentication

{

private string error = "";

private AuthenticationResultCode resultCode = AuthenticationResultCode.None;

private AuthenticationResult authResult = null;

public IPlatformParameters platformParameters

{

get;

set;

}

public AuthenticationResultCode ResultCode

{

get

{

return resultCode;

}

}

public AuthenticationResult AuthResult

{

get

{

return authResult;

}

}

public string Error

{

get

{

return error;

}

}

private ADALAuthentication()

{

}

private static ADALAuthentication instance = null;

public static ADALAuthentication Instance

{

get

{

if (instance == null)

{

instance = new ADALAuthentication();

}

return instance;

}

}

public async Task<AuthenticationResultCode> Authenticate(string resource, string clientId, string returnUrl)

{

try

{

AuthenticationContext ac = new AuthenticationContext("https://login.microsoftonline.com/common");

authResult = await ac.AcquireTokenAsync(resource, clientId, new Uri(returnUrl), platformParameters);

resultCode = AuthenticationResultCode.Succesfull;

}

catch (AdalException adalEx)

{

switch (adalEx.ErrorCode)

{

case "authentication_canceled":

resultCode = AuthenticationResultCode.Canceled;

break;

case "access_denied":

resultCode = AuthenticationResultCode.Denied;

break;

default:

resultCode = AuthenticationResultCode.Unknown;

break;

}

}

catch (Exception ex)

{

resultCode = AuthenticationResultCode.Unknown;

error = ex.Message + " " + ex.StackTrace;

}

return resultCode;

}

}

}

An important part of the authentication class is the Authenticate method which is described above. The method authenticates against Azure AD with ADAL and returns information containing the access token we need to have to access other resources like the Microsoft Graph.

The process of authentication is rather simple and requires the standard Microsoft URL https://login.microsoft.com/common to logon as a multi-tenant application. Normally the URL contains the id of the tenant. But using this URL without the tenant id will allow us to let users from other domains than the domain in which the application is registered to logon and use the resources (applications as Microsoft Graph) as specified.

After we have an AuthenticationContext we need to acquire the token to access the resources. This call is an asynchronous call and contains some parameters.

  • Resource – This is the URL of the resource you want to access. If you have delegated permissions to Microsoft Graph specified at the registration of the application, this is the domain URL of the Microsoft Graph API.
  • Client Id – This is the client id of the registration of the application in Azure AD.
  • Return URL – this is one of the return URLs specified in the registration of the application in Azure AD
  • Platform parameters – Theses platform parameters differ per platform (iOS, Android, Windows 10, e.g.) Later on we explain how to resolve this issue within the Xamarin project.

To get authenticated you need to make sure that the Client Id and the return URL are the same as in the registration of the application in Azure AD. If this is not the case, the authentication will fail. The code also contains some translations from the textual error codes returned from ADAL to a friendlier enumeration.

Understand PlatformParameters

When we authenticate against Azure AD through ADAL we use the AcquireTokenAsync method. That method expects an object based on the interface IPlatformParameters. Depending on the platform the object differs in its parameters.

Platform Parameter(s) Value
iOS Reference to a UIViewController UIApplication.SharedApplication.KeyWindow.RootViewController
Android Reference to an Activity (Activity)Forms.Context

Remark: You will need to override the OnActivityResult method in MainActivity.cs and call the WebAuthenticationBrokerContinuationHelper class.

Windows Phone No parameters N/A
Windows 10 (Universal) PromptBehavior, OrganizationOnly PromptBehavior.Auto, false

Because we are using a portable class library project it is not possible to put platform specific code in the classes of that library. That is the reason we need to provide per platform a different object based on IPlatformParameters to the ADALAuthentication class.

The next step is to implement the interface IADALAuthenticator per platform. For the iOS platform the code is as follow:

using Microsoft.IdentityModel.Clients.ActiveDirectory;

using System;

using System.Collections.Generic;

using System.Text;

using System.Threading.Tasks;

using UIKit;

using Xamarin.Forms;

[assembly: Dependency(typeof(ADALXamarinExample.iOS.ADALAuthenticator))]

namespace ADALXamarinExample.iOS

{

public class ADALAuthenticator : IADALAuthenticator

{

public Task<AuthenticationResultCode> Authenticate(string resource, string clientId, string returnUri)

{

ADALAuthentication.Instance.platformParameters = new PlatformParameters(UIApplication.SharedApplication.KeyWindow.RootViewController);

return ADALAuthentication.Instance.Authenticate(resource, clientId, returnUri);

}

}

}

We use the instance of the ADALAuthentication class to set the PlatformParameters and call the Authenticate method. For the Windows 10 platform the code is as follow:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Microsoft.IdentityModel.Clients.ActiveDirectory;

using Xamarin.Forms;

[assembly: Dependency(typeof(ADALXamarinExample.UWP.ADALAuthenticator))]

namespace ADALXamarinExample.UWP

{

public class ADALAuthenticator : IADALAuthenticator

{

public Task<AuthenticationResultCode> Authenticate(string resource, string clientId, string returnUri)

{

ADALAuthentication.Instance.platformParameters = new PlatformParameters(PromptBehavior.Auto, false);

return ADALAuthentication.Instance.Authenticate(resource, clientId, returnUri);

}

}

}

Again we use the instance of the ADALAuthentication class to set the PlatformParameters and call the Authenticate method.

In both classes you will notice a definition above the namespace of the class.

[assembly: Dependency(typeof(…))]

This definition allows us to retrieve the implementation of the platform specific class for ADALAuthenticator through DependencyService.Get<IADALAuthenticator>(). This is used when we are creating the login page.

Create a login page

For this demo we will create a LoginPage based on the base class ContentPage. This LoginPage is defined in the portable class library. It shows a single button on the screen. When the button is clicked, the user is redirected to the authentication page of Azure AD. After the authentication has been successful the username and group names are shown.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Reflection.Emit;

using System.Text;

using Microsoft.IdentityModel.Clients.ActiveDirectory;

using Xamarin.Forms;

namespace ADALXamarinExample

{

public class LoginPage : ContentPage

{

private Label results;

private Label groupResults;

async void getTokenButton_Clicked(object sender, EventArgs e)

{

var auth = DependencyService.Get<IADALAuthenticator>();

AuthenticationResultCode code = await auth.Authenticate("https://graph.microsoft.com", "6511dcf1-e288-445c-8688-fea17e4bf1e3", "http://localhost:8000");

switch (code)

{

case AuthenticationResultCode.Succesfull:

results.Text = "got a token for " + ADALAuthentication.Instance.AuthResult.UserInfo.GivenName;

break;

case AuthenticationResultCode.Canceled:

results.Text = "You have canceled authentication";

break;

case AuthenticationResultCode.Denied:

results.Text = "Your access is denied";

break;

default:

results.Text = ADALAuthentication.Instance.Error;

break;

}

}

public LoginPage()

{

var btnLogin = new Button

{

Text = "Login"

};

btnLogin.Clicked += getTokenButton_Clicked;

results = new Label();

groupResults = new Label();

Content = new StackLayout

{

Children =

{

btnLogin, results, groupResults

},

HorizontalOptions = LayoutOptions.Center,

VerticalOptions = LayoutOptions.Center

};

}

}

}

If you look at the code, you will notice that it only takes two lines of code to get authenticated. The first line of code gets the implementation of the IADALAuthenticator based on the platform you are running. The second line of code calls the Authenticate method with the resource URL, client id and the redirect URL.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Xamarin.Forms;

namespace ADALXamarinExample

{

public class App : Application

{

public App()

{

MainPage = new LoginPage();

}

}

}

Finally, we need to replace the existing code in the App class to make sure that our new LoginPage is called when the mobile application starts. We now have a Xamarin application which allows us to authenticate against Azure AD.

Implement code for getting groups

The next step is implementing a class for retrieving the Microsoft Groups the logged on user is anticipating in from Office 365 through the Microsoft Graph API. The result of a call to the REST API for Microsoft Groups will return a json payload. Therefor we are going to use the Newtonsoft.Json NuGet package to help us out.

This package gives us additional classes which allows us to retrieve the data from the json payload and makes it easier to process the json. The NuGet package needs only to be installed on the portable class library project.

using Newtonsoft.Json;

using Newtonsoft.Json.Linq;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Net.Http;

using System.Net.Http.Headers;

using System.Text;

using System.Threading.Tasks;

namespace ADALXamarinExample

{

public class GroupsManager

{

private string ListGroupsUrl = "https://graph.microsoft.com/v1.0/groups";

public class Group

{

public string Name = "";

}

public class Groups : List<Group>

{

}

public async Task<Groups> ListGroups(string accessToken)

{

Groups groups = new Groups();

using (var client = new HttpClient())

{

using (var request = new HttpRequestMessage(HttpMethod.Get, ListGroupsUrl))

{

request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

using (var response = await client.SendAsync(request))

{

if (response.StatusCode == HttpStatusCode.OK)

{

var json = JObject.Parse(await response.Content.ReadAsStringAsync());

JArray jsonGroups = (JArray)json["value"];

IList<JObject> arrayGroups = jsonGroups.Select(c => (JObject)c).ToList();

foreach (JObject obj in arrayGroups)

{

Group group = new Group();

group.Name = obj["displayName"].ToString();

groups.Add(group);

}

}

}

}

}

return groups;

}

}

}

The class is a very simple class and contains a definition for a Group object and a Group collection object. There is one method purely for demo purposes which retrieves the group names and creates a collection of Group objects. We use the HttpClient class to create a client object. Then we create a HttpRequestMessage object based on the REST API URL for retrieving the groups. An important part of this call is setting an authorization property in the header of the request. It is called the “Bearer” and contains the access token we got from the authentication through ADAL. Next we call the SendAsync method on the client object with the request object to retrieve the groups. We finally use the Newtonsoft.Json objects to extract the display name of the group and store it into our own objects.

Additionally, we need to add some code in the LoginPage to show the group names on the screen.

case AuthenticationResultCode.Succesfull:

results.Text = "got a token for " + ADALAuthentication.Instance.AuthResult.UserInfo.GivenName;

GroupsManager mgr = new GroupsManager();

GroupsManager.Groups groups = await mgr.ListGroups(ADALAuthentication.Instance.AuthResult.AccessToken);

foreach(GroupsManager.Group group in groups)

{

groupResults.Text += group.Name;

groupResults.Text += "rn";

}

break;

This code calls the GroupsManager class and retrieves all the groups. Each groups name is displayed in the label groupResults.

The result

When you run the application it shows a login button. By clicking on the button the user is redirected to the login page of Azure AD. In my case I’m using a work account and get that choice. The mobile applications request consensus as specified in the application in Azure AD. When the user approves and is authenticated he is redirected to that same login page. That page shows the name of the logged on user and the groups in which he anticipates.

The result voor Windows 10 will look as follow.

     

The result for the iOS platform (in this case a iPhone 6) will look as follow.

     
Previous articleDeveloping Windows Phone Apps in a Hyper-V environment using nested virtualization
Next articleGetting list items between dates from SharePoint using PowerShell
A professional which inspires, motivates and educates businesses on how to leverage emerging technologies using Virtual, Augmented and Mixed Reality in their journey to digital innovation. He has a strong background on SharePoint, Office 365 and Microsoft Azure and is working with machine learning, artificial intelligence and cognitive services. Primarily focused on manufacturing, construction, industry, logistics and maritime/offshore, his goal is helping businesses to achieve more on creating, improving, smartening and shortening of business processes by using services, apps and devices. Furthermore, he engages in speaking, blogging and is organizer of events like the Mixed Reality User Group, Mixed Reality Talk @ VR, SP&C and the Global AI/MR Bootcamp. With more than 20 years of IT Business experience, acting in different roles like solution architect, he believes the future is just starting! Highly experienced in all realities, HoloLens and other devices, User experiences on devices and connecting the world to the cloud will help him to shape that future!

7 COMMENTS

  1. Excellent article, I was getting stuck on PlatformParameters, this solved it and allowed me to continue with my project. Thanks

  2. This article is great and very easy to follow.
    It may happen on iOS that the controller returned by UIApplication.SharedApplication.KeyWindow.RootViewController is not the top most controller. So you may get issue to see the login page.

    I use this code

    // Identifies the top most view controller
    UIViewController currentController = UIApplication.SharedApplication.KeyWindow.RootViewController;
    while (currentController.PresentedViewController != null)
    currentController = currentController.PresentedViewController;

  3. Hey
    Thank for the blog.
    I am facing issue for android implementation.
    So the issue is when I call AcquireTokenAsync on WLAN it shows a blank screen on mobile where as working fine in a cellular network.
    I got an error msg “cannot call determinedvisibility()”, so can please help me for the same.

    • I’m thinking of a timing issue in this case. Due to the (expected) slower bandwidth of cellular it has some time to load everything to allow the call AcquireTokenAsync to work fine. When you WLAN is much quicker and is causing issues. You could try to build in something to slow done before doing the Async call.

  4. Hello Sir ,thank you fot yhis tutorial, i had error when i implement UWP Authentification

    private const string TenantUrl = “https://login.microsoftonline.com/common”;
    public static string ADClientId = “”;
    public static string tenant = “”;
    public static Uri returnUriId = new Uri(“”);
    public static string WebApiADClientId = “”;

    public async Task AuthenticationAsync()
    {
    try
    {
    var platformParams = new PlatformParameters(PromptBehavior.Auto, false);
    var authContext = new AuthenticationContext(TenantUrl);

    if (authContext.TokenCache.ReadItems().Any())
    {
    authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().FirstOrDefault().Authority);
    }

    var authResult = await authContext.AcquireTokenAsync(WebApiADClientId, ADClientId, returnUriId, platformParams);

    return new ADToken()
    {
    AccessToken = authResult.AccessToken,
    TokenType = authResult.AccessTokenType,
    Expires = authResult.ExpiresOn.Ticks,
    UserName = authResult.UserInfo.DisplayableId
    };
    }
    catch (Exception ex)
    {
    throw ex;
    }
    }

LEAVE A REPLY

Please enter your comment!
Please enter your name here