Authenticating to Azure AD non-interactively


fingerprint-1382652_640I want to use Azure AD as a user directory but I do not want to use its native web authentication mechanism which requires users to go via an Active Directory page to login (which can be branded and customized to look like my own).

I just want to give a user name & password to an authentication API.

The reason is I want to migrate an existing application currently using an LDAP server and want to change the code as little as possible.

You might have other reasons why you want to do that.

Let’s just say that the online literature HEAVILY leans towards using the web workflow.  Even the documentation on native apps recommends that your native app pops the Azure AD web page to authenticate the user.  There are good reasons for that as this way your app never touches user credentials and is therefore more secure and your app more trustworthy.  So in general, I totally agree with those recommendations.

But in my case, my legacy app is touching the user credentials all over the place.  Also this approach is a stepping stone before considering moving to the web workflow.

After a weekend spent scanning the entire web (as a side note I’ve learned there was little Scandinavian men living inside the Earth, which is flat by the way), I finally found Danny Strockis’ article about Authenticating to Azure AD non-interactively using a username & password.

That is it basically.  Except the article is a little quick on setup, so I’m gona elaborate here.

I’m going to give a sample in C# using ADAL, but since at the end of the day, the authentication is one HTTP POST, I’ll also give a more bare bone sample using HTTP post if you don’t want or cannot to integrate with ADAL.  The samples are quite trivial so you should be able to convert them in the language / platform of your choice.

Conceptually

We basically want our users to interact with our application only, punch in their credentials and have the application check with Azure AD if the credentials are good.

image

Here the application is represented as a Web app here but it could also be a native application.

In order to do this in the world of Azure AD is to use two Azure AD apps:

  1. A client app, representing the agent authenticating the user
  2. A service app, representing the actual application the user is authenticating against

I know it looks weird, it makes your brain hurts and is in great part the reason I’m writing this article, because it isn’t straightforward.

image

In the authentication parlance, the client App is the client (so far so good) while the service app is the resource, i.e. the thing the user is trying to access:  the client is accessing the resource on the user’s behalf.

Setting up Azure AD

Yes, there will be some steps to setup Azure AD.

First we need a tenant.  We can use the tenant used by our subscription but typically for those types of scenario we’ll want to have a separate tenant for our end users.  This article shows how to create an Azure AD tenant.

We then need a user to test.  We can create a user like this:

image

where, of course, ldapvpldemo is my Azure AD tenant.

We’ll also need to give that user a “permanent” password, so let’s show the password on creation (or reset it afterwards) then let’s go to an InPrivate browsing window and navigate to https://login.microsoftonline.com/.  We can then login as the user (e.g. test@ldapvpldemo.onmicrosoft.com) with the said password.  We’ll be prompted to change it (e.g. My$uperComplexPassw0rd).

Let’s create the client app.  In App Registrations, let’s add an app with:

image

It would probably work as a Web app / API but a Native App seems more fitting.

We’ll need the Application ID of that application which we can find by looking at the properties of the application.

image

We then need to create the service app:

image

We’ll need the App ID URI of the service:

image

That URI can be changed, either way we need the final value.

We will need to give permission to the client app to access the service app.  For that we need to go back to the client app, go to the Required Permissions menu and add a permission.  From there, in the search box we can just start to write the name of the service app (e.g. MyLegacyService) and it should appear where we can select it.  We then click the Access MyLegacyService box.

Finally, we need to grant the permissions to users.

image

With all that, we’re ready to authenticate.

ADAL

This sample is in C# / .NET but since ADAL is available on multiple platform (e.g. Java), this should be easy to port.

We’ll create a Console Application project.  We need the full .NET Framework as the .NET core version of ADAL doesn’t have the UserPasswordCredential class we’re gona be using.

We need to install the NuGet package Microsoft.IdentityModel.Clients.ActiveDirectory in the project.

        private static async Task AdalAuthenticationAsync()
        {
            //  Constants
            var tenant = "LdapVplDemo.onmicrosoft.com";
            var serviceUri = "https://LdapVplDemo.onmicrosoft.com/d0f883f6-1c32-4a14-a436-0a995a19c39b";
            var clientID = "b9faf13d-9258-4142-9a5a-bb9f2f335c2d";
            var userName = $"test@{tenant}";
            var password = "My$uperComplexPassw0rd1";

            //  Ceremony
            var authority = "https://login.microsoftonline.com/" + tenant;
            var authContext = new AuthenticationContext(authority);
            var credentials = new UserPasswordCredential(userName, password);
            var authResult = await authContext.AcquireTokenAsync(serviceUri, clientID, credentials);
        }

We have to make sure we’ve copied the constants in the constant section.

This should work and authResult should contain a valid access token that we could use as a bearer token in different scenarios.

If we pass a wrong password or wrong user name, we should obtain an error as expected.

HTTP POST

We can use Fiddler or other HTTP sniffing tool to see what ADAL did for us.  It is easy enough to replicate.

        private static async Task HttpAuthenticationAsync()
        {
            //  Constants
            var tenant = "LdapVplDemo.onmicrosoft.com";
            var serviceUri = "https://LdapVplDemo.onmicrosoft.com/d0f883f6-1c32-4a14-a436-0a995a19c39b";
            var clientID = "b9faf13d-9258-4142-9a5a-bb9f2f335c2d";
            var userName = $"test@{tenant}";
            var password = "My$uperComplexPassw0rd";

            using (var webClient = new WebClient())
            {
                var requestParameters = new NameValueCollection();

                requestParameters.Add("resource", serviceUri);
                requestParameters.Add("client_id", clientID);
                requestParameters.Add("grant_type", "password");
                requestParameters.Add("username", userName);
                requestParameters.Add("password", password);
                requestParameters.Add("scope", "openid");

                var url = $"https://login.microsoftonline.com/{tenant}/oauth2/token";
                var responsebytes = await webClient.UploadValuesTaskAsync(url, "POST", requestParameters);
                var responsebody = Encoding.UTF8.GetString(responsebytes);
            }
        }

Basically, we have an HTTP post where all the previous argument are passed in the POST body.

If we pass a wrong password or wrong user name, we should obtain an error as expected.  Interestingly, the HTTP code is 400 (i.e. bad request) instead of some unauthorized variant.

Summary

Authenticating on an Azure AD tenant isn’t the most recommended method as it means your application is handling credentials whereas the preferred method delegate to an Azure AD hosted page the handling of those credential so your application only see an access token.

But for a legacy migration for instance, it makes sense.  Azure AD definitely is more secure than an LDAP server sitting on a VM.

We’ve seen two ways to perform the authentication.  Under the hood they end up being the same.  One is using the ADAL library while the other uses bare bone HTTP POST.

Keep in mind, ADAL does perform token caching.  If you plan to use it in production, you’ll want to configure the cache properly not to get strange behaviours.

Advertisements

3 thoughts on “Authenticating to Azure AD non-interactively

  1. Pingback: Using Microsoft Graph API to interact with Azure AD | Vincent-Philippe Lauzon's blog

  2. Pingback: Automating Azure AD | Vincent-Philippe Lauzon's blog

  3. Pingback: Azure Weekly: Feb 6, 2017 – Build Azure

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s