How to create a Custom Authentication Provider for Active Directory Federation Services on Windows Server 2012 R2 - Part 4

In this series of five blog posts I want to show you how you can create your own Authentication Provider in AD FS on Windows Server 2012 R2. This Authentication Provider can then be used in AD FS for multi-factor authentication (MFA). The solution will use the users mobile device as a second factor for authentication, by sending a One-Time Password (OTP) or PIN to the device.

For those of you interested only in the AD FS related components, part 2 will be most interesting. That's where we will be creating the Authentication Provider itself. But if you are looking for a complete, working, solution, you might want to go over the entire set. So you might be interested by now what's in the other parts... or at least I hope you are. So here's a quick agenda;

  1. Introduction
  2. Creating the Authentication Provider
  3. Setting up Azure Mobile Services
  4. Creating a Windows Phone Authenticator App
  5. Putting it all together

Now, before we get started I have to remind you that this blog post series is only to show you how you can create this Authentication Provider. By no means is the solution we are creating an enterprise ready MFA solution. If you are looking into such an enterprise ready solution, I would recommend you take a look at the Windows Azure Multi-Factor Authentication.

Now... Let's get going with Part 4: Creating a Windows Phone Authenticator App.

Part 4 - Creating a Window Phone Authenticator App

Since we want to achieve Multi-Factor Authentication in our Authentication Provider for AD FS on Windows Server 2012 R2, we need to be able to properly work with a something the users owns. A phone is very convenient! So we have already created the Windows Azure Mobile Service to facilitate our toast notifications. What's still left is to create an application that subscribes to these toast messages. Furthermore, we need something to uniquely identify the mobile device. We don't any mobile device the user has or any (rogue) application to be use for our MFA. In this part we are going to create a super simple Windows Phone 8 App that does these two things; displays the unique ID to the user (so the administrator can add that unique id to the users AD account so that our Authentication provider can use it) and it listens to the toast messages (containing the PIN) sent by our Authentication Provider.

Requirements

Building the Windows Phone Authenticator App

Our app will be small. It does only two things. Furthermore, since we already created something in Part 2 - Creating the Authentication Provider, I'm sure that we now all know how to create a new project in Visual Studio. So go ahead and create a new Windows Phone App Project. Let's call our project MyPhoneAuthenticator.

After the project has been created, open the Package Manager Console (at the bottom of the screen, or click TOOLS, Library Package Manager, Package Manager Console.)
In the Package Manager Console screen, type the command to install the client libraries for Windows Azure Mobile Services;

Install-Package WindowsAzure.MobileServices

Check the output to see if all libraries have been successfully installed. The output should resemble this;

PM> Install-Package WindowsAzure.MobileServices
Attempting to resolve dependency 'Newtonsoft.Json (≥ 5.0.8)'.
Attempting to resolve dependency 'Microsoft.Bcl (≥ 1.1.3)'.
Attempting to resolve dependency 'Microsoft.Bcl.Build (≥ 1.0.10)'.
Attempting to resolve dependency 'Microsoft.Net.Http (≥ 2.2.15)'.
Installing 'Newtonsoft.Json 5.0.8'.
Successfully installed 'Newtonsoft.Json 5.0.8'.
Installing 'Microsoft.Bcl.Build 1.0.13'.
You are downloading Microsoft.Bcl.Build from Microsoft, the license agreement to which is available at https://go.microsoft.com/fwlink/?LinkId=329770. Check the package for additional dependencies, which may come with their own license agreement(s). Your use of the package and dependencies constitutes your acceptance of their license agreements. If you do not accept the license agreement(s), then delete the relevant components from your device.
Successfully installed 'Microsoft.Bcl.Build 1.0.13'.
Installing 'Microsoft.Bcl 1.1.6'.
You are downloading Microsoft.Bcl from Microsoft, the license agreement to which is available at https://go.microsoft.com/fwlink/?LinkId=329770. Check the package for additional dependencies, which may come with their own license agreement(s). Your use of the package and dependencies constitutes your acceptance of their license agreements. If you do not accept the license agreement(s), then delete the relevant components from your device.
Successfully installed 'Microsoft.Bcl 1.1.6'.
Installing 'Microsoft.Net.Http 2.2.18'.
You are downloading Microsoft.Net.Http from Microsoft, the license agreement to which is available at https://go.microsoft.com/fwlink/?LinkId=329770. Check the package for additional dependencies, which may come with their own license agreement(s). Your use of the package and dependencies constitutes your acceptance of their license agreements. If you do not accept the license agreement(s), then delete the relevant components from your device.
Successfully installed 'Microsoft.Net.Http 2.2.18'.
Installing 'WindowsAzure.MobileServices 1.1.2'.
You are downloading WindowsAzure.MobileServices from Microsoft, the license agreement to which is available at https://go.microsoft.com/fwlink/?LinkId=286110. Check the package for additional dependencies, which may come with their own license agreement(s). Your use of the package and dependencies constitutes your acceptance of their license agreements. If you do not accept the license agreement(s), then delete the relevant components from your device.
Successfully installed 'WindowsAzure.MobileServices 1.1.2'.
Adding 'Newtonsoft.Json 5.0.8' to MyPhoneAuthenticator.
Successfully added 'Newtonsoft.Json 5.0.8' to MyPhoneAuthenticator.
Adding 'Microsoft.Bcl.Build 1.0.13' to MyPhoneAuthenticator.
Successfully added 'Microsoft.Bcl.Build 1.0.13' to MyPhoneAuthenticator.
Adding 'Microsoft.Bcl 1.1.6' to MyPhoneAuthenticator.
Successfully added 'Microsoft.Bcl 1.1.6' to MyPhoneAuthenticator.
Adding 'Microsoft.Net.Http 2.2.18' to MyPhoneAuthenticator.
Successfully added 'Microsoft.Net.Http 2.2.18' to MyPhoneAuthenticator.
Adding 'WindowsAzure.MobileServices 1.1.2' to MyPhoneAuthenticator.
Successfully added 'WindowsAzure.MobileServices 1.1.2' to MyPhoneAuthenticator.

These libraries will make it very easy to have our application use the Windows Azure Mobile Service we created in the previous part.

By creating the Windows Phone Application, the MailPage.xaml file should be opened and will display the phone app next to the XAML code.
In the XAML code locate this part;

         <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

        </Grid>

and put this code between these two lines:

            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Row="0" Text="This is a demo application to demonstrate multi factor authentication in AD FS using a custom Authentication Provider." TextWrapping="Wrap" Margin="12"/>
            <TextBlock Grid.Row="1" Text="Your Device ID is:" TextAlignment="Center" TextWrapping="Wrap" Margin="12" />
            <TextBlock Grid.Row="2" TextWrapping="Wrap" TextAlignment="Center"  Text="{Binding deviceId}" Margin="12" FontFamily="Courier New" FontSize="36" />

Your Phone App should now look like this in Visual Studio;

Now, make sure the application's form is selected by either clicking on the top of the preview screen (on the left) or by clicking on the <phone:PhoneApplicationPage.. text in the XAML screen. Then, in the Properties window on the right, make sure that Type equals PhoneApplicationPage and click on the Event Handlers button to show the implement events for the object. Locate the Loaded event en double-click in the empty space behind it.

After double-clicking in the empty space next to the Loaded event, the PhoneApplicationPage_Loaded event implementation will be created in your application. Please add this line to the event handler;

 ContentPanel.DataContext = this;

In the same class, MainPage, add a property that holds the unique identifier for the device. A textbox on the main page is bound to this property.

         public string deviceId
        {
            get { return Windows.Phone.System.Analytics.HostInformation.PublisherHostId; }
            set { }
        }

You MainPage class in Visual Studio should look like this:

Now, create a new Class called Registrations that will be used to register the application with our Windows Azure Mobile Service. If you don't recall how to do this, please take a look at Part 2
Then, add a using statement for the Newtonsoft.Json namespace:

 using Newtonsoft.Json;

Implement the Registrations class like this:

     public class Registrations
    {
        public string Id { get; set; }

        [JsonProperty(PropertyName = "handle")]
        public string Handle { get; set; }

        [JsonProperty(PropertyName = "deviceid")]
        public string DeviceId { get; set; }
    }

Now we need to add some code to the App.xaml.cs file. Open this file by double-clicking on App.xaml.cs under App.xaml in the Solution Explorer.

In the App.xaml.cs add these using statements:

using Microsoft.Phone.Notification;
using Microsoft.WindowsAzure.MobileServices;

Also, make te following additions to the App class:

         public static MobileServiceClient MobileService = new MobileServiceClient("https://myauthenticationprovider.azure-mobile.net/", "kx5IznPLilXrhKlBBO6HNvmhPepIrr75");

        public static HttpNotificationChannel CurrentChannel { get; private set; }
        
        private async void AcquirePushChannel()
        {
            CurrentChannel = HttpNotificationChannel.Find("MyPushChannel");

            if (CurrentChannel == null)
            {
                CurrentChannel = new HttpNotificationChannel("MyPushChannel");
                CurrentChannel.Open();
                CurrentChannel.BindToShellToast();
            }

            while (CurrentChannel.ChannelUri == null)
            {
                System.Threading.Thread.Sleep(100);
            }

            IMobileServiceTable<Registrations> registrationsTable = App.MobileService.GetTable<Registrations>();
            var registration = new Registrations { Handle = CurrentChannel.ChannelUri.ToString(), DeviceId = Windows.Phone.System.Analytics.HostInformation.PublisherHostId };

            await registrationsTable.InsertAsync(registration);
        }

Make sure that this line;

new MobileServiceClient("https://myauthenticationprovider.azure-mobile.net/", "kx5IznPLilXrhKlBBO6HNvmhPepIrr75");

lists the URL of your own Windows Azure Mobile Service and that the code behind it is the APPLICATION KEY that you wrote down at the end of Part 3.

In the Application_Launching method, add this line:

AcquirePushChannel();

So what did we just create?

First of all, we wanted to the unique ID of the device. This is achieved through the property Windows.Phone.System.Analytics.HostInformation.PublisherHostId. This is a string that uniquely identifies a device. This string is unique per device and per publisher, which means that no two publishers will receive the same value for the same device. This value is shown on the screen of the device.

Second, we want to register the device with out Windows Azure Mobile Service in order to receive Toast messages from the service. We have created a class (Registrations) that resembles the Registrations table in the service and can be used to insert a registration entry in the services' database. The lines of code that create the actual communications channel are:

CurrentChannel = new HttpNotificationChannel("MyPushChannel");
CurrentChannel.Open();
CurrentChannel.BindToShellToast();

The information on the resulting channel is the stored in the Registrations table in the Mobile Service;

IMobileServiceTable<Registrations> registrationsTable = App.MobileService.GetTable<Registrations>();
var registration = new Registrations { Handle = CurrentChannel.ChannelUri.ToString(), DeviceId = Windows.Phone.System.Analytics.HostInformation.PublisherHostId };
await registrationsTable.InsertAsync(registration);

Compiling the Windows Phone App

Before we can run the Windows Phone App on our Windows Phone, we need to tell the application what we are going to do. Go to the Solution Explorer, and expand Solution, MyPhoneAuthenticator and Properties.

There, double click on WMAppManifest.xml.

In the WMAppManifest.xml that opens, select the Capabilities tab and check the boxes for ID_CAP_IDENTITY_DEVICE and ID_CAP_PUSH_NOTIFICATION.

Not setting the ID_CAP_IDENTITY capability will cause the code to fail; you will get an Access Denied message when we try to access Windows.Phone.System.Analytics.HostInformation.PublisherHostId. So it's important that we properly set these capabilities.

We are now ready to deploy the application to our Mobile device. Connect your Windows Phone 8 device to your computer and unlock the screen. In Visual Studio select Device to run the project on.

Now, deploy the project to your device by clicking BUILD and Deploy Solution.

Once the application has been deployed to your phone, we can see it as MyAuthenticationProvider in the list of Apps.

Tap the title, and the application will start. It will directly show you the device id.

Everything appears to work. The only thing we need to check is if the application really connected to our Mobile Service and registered the device. Note the Device ID that App shows you. We'll see if we can find this in the Registrations table in our Mobile Service.

Navigate to https://manage.windowsazure.com and log on with your Microsoft Account. Open the Mobile Service that you created and click on the Registrations table. Then, click on BROWSE.

If all went well, we should see one entry in the Registrations table. The deviceid shown by the device should match the deviceid in the Registrations table.

Our Windows Phone 8 App that will receive Toast notifications is now ready. The only thing left is that we revise the AD FS Authentication Provider to take use of the Mobile Service that we created.

Take me to Part 5 - Putting it all together

Take me back to Part 3 - Setting up Azure Mobile Services