Background
Microsoft has recently released the Azure Active Directory Graph Client Library for .NET. This library wraps up the Azure Active Directory Graph API, making it much simpler to use for .NET developers. I’ve been working with a non-profit lately in their Office 365 environment and we’ve been building an application that delegates user management in their related Azure Active Directory environment. As a result, we’ve learned a LOT about the new Client Library. So, I thought I’d share some of the first steps in developing an application that runs against Azure Active Directory using the new Client Library. In the case of this non-profit, 100% of the systems are in Azure/Office 365. There are no on-premises installations.
Creating an Azure application
The first step in utilizing the Client Library is to create an application in your Azure portal. If you’re using Office 365, you’re also given an Azure subscription with Active Directory for free. However, the first time you attempt to login to the Azure portal with your Office 365 credentials, you’ll be asked for a credit card for incidental charges.
To create an application, first login to the Azure portal (note: as of 2/11/2015, the newest Azure portal [with the blades] does not have the capability to manage Azure Active Directory):
Scroll down on the left side and click Active Directory:
In the Active Directory window that loads, click on the name of your directory:
When your directory window loads, click the Applications link at the top:
In the Applications window, click the Add button at the bottom:
In the window that opens, select the ‘Add an application my organization is developing’ link:
In the ‘Add application’ window, add a name for your application and select your type of application. This is completely arbitrary. Then click the right arrow.
The Azure Active Directory Application functionality is really designed to allow authentication to applications to be performed via Azure Active Directory. As such, Azure will ask for URLs to route users for authentication to the system. In our case, we’re using the Azure Active Directory Applications slightly differently, so we’ll just put in some arbitrary values in the fields. In this case, I’m using the default tenant domain for my Microsoft Office Division Demo tenant. These values can be changed later, if need be. Click the check mark in the bottom right after you’ve completed entering your data.
After the application has been created, click on the Configure button at the top:
This where we’ll gather the Client ID and Key for the new application. As you can see, the Client ID has already been created. We need to create the Key as well. To do that, scroll down to the ‘keys’ section and select a duration from the drop down box. This will add a new key that has the value hidden. Next, scroll down to the ‘permissions to other applications’ section. The Windows Azure Active Directory application has already been added. Under the ‘Application Permissions’ drop down, select “Read and write directory data”:
Finally, click Save. This will generate your Key. Copy your Client ID and Key to somewhere safe, as the Key will not be visible again after leaving this page.
Note: I’m displaying the Key here so that it’s clear what I’m describing, and by the time you read this, my application and Key will have been deleted. However, protect this key like you would protect a Domain Administrator account in your on-premises environment. It could be a powerful entryway into your environment for the unsavory types of people!
Phew! It seems like a lot of steps, but really it only takes a few seconds to complete once you’ve done it once or twice. Now, on to something fun!
Working with the Client Library
If you’re still reading this, I’m going to assume that you’re at least a little bit familiar with .NET/C#. For this example, I’m just going to use a run of the mill console application. I’ll start with a new console application and walk through all of the steps so that you’re not worried that there’s some magic trickery happening in the background.
First, launch your application’s solution/project in Visual Studio. In my case, I’m going to start a brand new console application in Visual Studio 2013 Ultimate.
Next, right click the project and select ‘Manage NuGet packages…’:
In the ‘Manage NuGet Packages’ window that opens, select the Online option on the left and search for Azure Active Directory Graph Client Library:
When the NuGet package manager is done searching, click install on the ‘Microsoft Azure Active Directory Graph Client Library’ package:
The NuGet package manager might ask you to accept some various licenses. Accept those licenses (be sure to read them if you’re going to use them in an actual project!) and then the package should start to install:
Next, install the Active Directory Authentication Library, again reading and accepting licenses if need be:
’When the packages are done installing, close the NuGet package manager window:
If you expand the References section in your project, you can now see the new Microsoft.Azure.ActiveDirectory.GraphClient and Microsoft.IdentityModel.Clients.ActiveDirectory libraries, along with some additional supporting libraries installed in your project:
Now, let’s write some code. First, let’s create the ActiveDirectoryClient object that we’ll be using to interact with Azure AD. You’ll need to add the ‘Microsoft.Azure.ActiveDirectory.GraphClient’ using at the top of your code, like so:
using Microsoft.Azure.ActiveDirectory.GraphClient;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AzureADGraphClientDemo
{
class Program
{
static string _azureDomain = "jonhussdemo.onmicrosoft.com"; // This is the domain from the Domains tab in the Azure Active Directory portal
static void Main(string[] args)
{
ActiveDirectoryClient activeDirectoryClient = new ActiveDirectoryClient(new Uri("https://graph.windows.net/" + _azureDomain),
async () => { return await GetAccessToken(); });
}
}
}
If you look closely, you’ll see there’s an async call to GetAccessToken(). This function is where we put together all of the Client IDs, Keys, URLs, etc. to gain an access token, allowing us to read from Azure Active Directory. That function looks like this and requires adding the ‘Microsoft.IdentityModel.Clients.ActiveDirectory’ using at the top:
private static async Task<string> GetAccessToken()
{
string clientID = "a484dd2f-c252-427a-a021-cfc83ad9ad6a"; // The Client ID that we retrieved from the Azure Applications portal
string key = "bdOB0aE9C9Rma5boXHxLYzCboBZ2W0x0O2a5uCILXLs="; // The Client Key that we generated in the Azure Applications portal
AuthenticationContext context = new AuthenticationContext("https://login.windows.net/" + _azureDomain + "/oauth2/token");
ClientCredential credential = new ClientCredential(clientID, key);
AuthenticationResult token = context.AcquireToken("00000002-0000-0000-c000-000000000000/graph.windows.net@" + _azureDomain, credential);
return token.AccessToken;
}
So, our code now looks like this:
using Microsoft.Azure.ActiveDirectory.GraphClient;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AzureADGraphClientDemo
{
class Program
{
static string _azureDomain = "jonhussdemo.onmicrosoft.com"; // This is the domain from the Domains tab in the Azure Active Directory portal
static void Main(string[] args)
{
ActiveDirectoryClient activeDirectoryClient = new ActiveDirectoryClient(new Uri("https://graph.windows.net/" + _azureDomain),
async () => { return await GetAccessToken(); });
}
private static async Task<string> GetAccessToken()
{
string clientID = "a484dd2f-c252-427a-a021-cfc83ad9ad6a"; // The Client ID that we retrieved from the Azure Applications portal
string key = "bdOB0aE9C9Rma5boXHxLYzCboBZ2W0x0O2a5uCILXLs="; // The Client Key that we generated in the Azure Applications portal
AuthenticationContext context = new AuthenticationContext("https://login.windows.net/" + _azureDomain + "/oauth2/token");
ClientCredential credential = new ClientCredential(clientID, key);
AuthenticationResult token = context.AcquireToken("00000002-0000-0000-c000-000000000000/graph.windows.net@" + _azureDomain, credential);
return token.AccessToken;
}
}
}
This code alone should give us access to our tenant’s directory, but it doesn’t really do anything. To look up a particular user, we can do something like this, using LINQ to pass in the user’s UserPrincipalName:
IUser user = activeDirectoryClient.Users.Where(u => u.UserPrincipalName == "admin@jonhussdemo.onmicrosoft.com").ExecuteSingleAsync().Result;
Console.WriteLine("DisplayName: " + user.DisplayName);
Console.WriteLine("GivenName: " + user.GivenName);
Console.WriteLine("Surname: " + user.Surname);
Which gives us the following result:
Similarly, we can look for security groups, like this:
IGroup group = activeDirectoryClient.Groups.Where(g => g.DisplayName == "Project Falcon").ExecuteSingleAsync().Result;
Console.WriteLine("DisplayName: " + group.DisplayName);
Console.WriteLine("Mail: " + group.Mail);
Which results in:
The complete code with these two sample searches looks like this:
using Microsoft.Azure.ActiveDirectory.GraphClient;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AzureADGraphClientDemo
{
class Program
{
static string _azureDomain = "jonhussdemo.onmicrosoft.com"; // This is the domain from the Domains tab in the Azure Active Directory portal
static void Main(string[] args)
{
ActiveDirectoryClient activeDirectoryClient = new ActiveDirectoryClient(new Uri("https://graph.windows.net/" + _azureDomain),
async () => { return await GetAccessToken(); });
IUser user = activeDirectoryClient.Users.Where(u => u.UserPrincipalName == "admin@jonhussdemo.onmicrosoft.com").ExecuteSingleAsync().Result;
Console.WriteLine("DisplayName: " + user.DisplayName);
Console.WriteLine("GivenName: " + user.GivenName);
Console.WriteLine("Surname: " + user.Surname);
IGroup group = activeDirectoryClient.Groups.Where(g => g.DisplayName == "Project Falcon").ExecuteSingleAsync().Result;
Console.WriteLine("DisplayName: " + group.DisplayName);
Console.WriteLine("Mail: " + group.Mail);
}
private static async Task<string> GetAccessToken()
{
string clientID = "a484dd2f-c252-427a-a021-cfc83ad9ad6a"; // The Client ID that we retrieved from the Azure Applications portal
string key = "bdOB0aE9C9Rma5boXHxLYzCboBZ2W0x0O2a5uCILXLs="; // The Client Key that we generated in the Azure Applications portal
AuthenticationContext context = new AuthenticationContext("https://login.windows.net/" + _azureDomain + "/oauth2/token");
ClientCredential credential = new ClientCredential(clientID, key);
AuthenticationResult token = context.AcquireToken("00000002-0000-0000-c000-000000000000/graph.windows.net@" + _azureDomain, credential);
return token.AccessToken;
}
}
}
Final Thoughts
Hopefully this walkthrough has been helpful to get you started using the Azure Active Directory Graph Client Library. The code was written to be as straightforward as possible. Naturally, if you intend to use similar code in an actual project, you’ll want to use things like config files to ease your management of the various URLs and keys. You can also find an extensive sample of the various functions that can be performed using the Client Library at https://github.com/AzureADSamples/ConsoleApp-GraphAPI-DotNet/blob/master/GraphConsoleAppV3/Program.cs. This sample includes tasks such as creating users and groups, resetting user passwords, enumerating pages of results, and much, much more.
Awesome, yes?
Brilliant thanks Jonathan – Very clear and complete
I have tested your sample included in an console application and it works perfectly. Can you tellm me why this is not working included in an web application? I have no clue.
Hi Ron,
There’s a reasonable chance that your problem has to do with the async model. Check out this post: http://blog.jonathanhuss.com/application-hang-when-executing-authenticationcontext-acquiretokenasync/
Jonathan
great article.Helps. Do you know, if there is a possibility to retrieve password policies using this library>
Hi Mandar,
I don’t believe so. It’s also worth noting that the Azure AD Graph API is being deprecated in favor of Microsoft Graph. There looks to be quite a bit of stuff coming in the next beta release of Microsoft Graph, so it may be available with those updates.
Jonathan
When you call AcquireToken where does the “00000002-0000-0000-c000-000000000000” come from?
Hi Shelby,
I’m not entirely sure the background. It’s just a known, static value that’s used for this identification.
Jonathan
Hello Jonathan,
Thank you so much for your excellent explanation.
Since github repo for this project was not available I tried to create you project locally. When I run, I get an error saying AADSTS90002: Tenant ‘token’ not found. This may happen if there are no active subscriptions for the tenant. Check with your subscription administrator.
Do you know why I get this error?