Sunday, 11 May 2014

Implementing Azure AD Group Authorization

In my last article we talked about
implementing AD single sign-on authentication to an MVC5 website, now we're going to look at adding AD group authorization to a controller with a customised AuthorizeAttribute implementation. Azure AD doesn’t currently
allow addition or custom roles, there are a number of built-in administrator
roles; however we have full control over groups so we can use these for
authorization.

Unfortunately
authorization isn’t as simple as just using the Authorize attribute with a role
as you would with ASP.Net roles, we need to query the Azure AD Graph API to
check if a user is a member of the
group. We’ll add a Sales group to the AzureBakery AD we created in the last article and then implement a
custom AuthorizeAttribute to query the Azure AD Graph API using the Azure AD
Graph client.

This was written for an MVC controller but can be used for a Web API controller and could used with Azure Mobile Services too.

We’re going to use the
Azure AD PowerShell module to modify the AD Application service principal later
in the procedure, so install this first.

Creating an AD Group

1.First go
the AD GROUP workspace in the portal for our Active Directory and click ADD
GROUP on the toolbar:

2.Enter a
name and description of the group and click the tick button to create it:

3.Next click
on the newly created group and then ADD MEMBERS on the toolbar:

4.In the Add
members dialog, click on the AD user we created to add it to the SELECTED list
and click the tick button to confirm:

5.Now go to
the GROUP CONFIGURE tab and make a note of the OBJECT ID, we’ll need this
later.

6.Next we
need to create a key for our application to allow us to access the graph API,
so create a new key in the APPLICATION workspace CONFIGURE tab:

7.Make a
note of this and the CLIENT ID.

8.We need to
create keys for the local and Azure AD applications.

Modifying the Application Service Principal

We need to modify
our application’s Service Principal so that it has permission to access the
Graph API, in theory this should be done by adjusting the permissions to other
applications section of the APPLICATION CONFIGURATION tab but at the time of
writing this it doesn’t work. Please try it yourself and if it doesn’t work for
you (you will get an unauthorized exception in the AD Graph API Client) use the
following procedure to manually add the service principal to an administrator
role:

1.Launch the
Azure AD PowerShell Console (from the desktop shortcut if you chose to use it).

2.First we
need to obtain our AD credentials, so type the following command and enter your
AD user credentials when prompted:

$msolcred = get-credential

This stores the credentials in a variable called $msolcred.

3.Next we
need to connect the console by typing the following command:

connect-msolservice -credential $msolcred

For a quick test, we can use the get-msoluser command to list AD users.
We should see something like this:

PS C:\WINDOWS\system32> get-msoluser

UserPrincipalName
DisplayName
isLicensed

-----------------
-----------
----------

gwebbercross_outlook.co... Geoff Webber-Cross False

geoff@azurebakery.onmic... Geoff False

4.Now we
need to get the service principal for our application using the following
command (get the CLIENT ID from CONFIGURE tab of the AD APPLICATION workspace
for the application associated with the website):

Implementing AzureAdAuthorizeAttribute

We’re going to
create a class called AzureAdAuthorizeAttribute which can be added to a
controller with either a group name or group ObjectId specified. The ObjectId
implementation is more efficient as it doesn’t require an additional query to
look up the id from the name.

We need to install the Microsoft.Azure.ActiveDirectory.GraphClient and Microsoft.IdentityModel.Clients.ActiveDirectory Microsoft.IdentityModel.Clients.ActiveDirectory NuGet packages by entering the following commands:

Install-Package Microsoft.Azure.ActiveDirectory.GraphClient

Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory

This is the complete
code for the attribute, the comments in the code explain what’s going on: