Introduction
Getting started with accessing Microsoft Graph in Azure can be a complex task. Not only are you required to make the necessary configuration changes in Azure to allow access to Graph, but most of the documentation on the subject is either incorrect, outdated or does not give you the complete solution.
Background
In this post, I will show, in six simple steps, how you configure Azure to allow access to Microsoft Graph. In addition, we will look at a C# console application that performs all necessary steps to retrieve information from Graph.
Configure Azure
In this example, we create a new app registration for tokenized access to Microsoft Graph and add full read permissions to Azure Active Directory.
- Create a new App Registration in your Azure AD.
- On the Authentication page, check the Access Tokens checkbox and Save.
- On the Certificates and secrets page, click New client secret, enter a description, select Expiry rule and click Add.
- Remember to Copy the secret before leaving the page, it will only be viewable once.
- On the API permissions page, click Add a permission > Microsoft Graph > Application Permission, and select Directory > Directory.Read.All.
- If Admin consent is required, follow the on screen instructions to Grant consent.
It is as simple as that. In order to continue with the sample code, we need to collect some meta data from Azure.
Client Secret
The client secret is used to authenticate the client against Azure. You should have copied it in step 4 and it should look something like this:
y3Dk3SfKa[XtK46SvET@C:vrUxt.uDF2
Authority
The authority is the service that is responsible for performing the authentication, in this case, we use Microsoft Graph:
https://graph.microsoft.com
Directory (Tennant)
This is the identity of your Azure Active Directory where you created the App Registration. To find this ID, go to the App Registration page in your Azure AD and click on the App Registration you created in step one and the overview page will show you the Directory identity like this:
Directory (tennant) ID : 4999ebad-131b-49f8-836b-cfe343676765
Application (client)
The application identity can be found on the same page as the Directory identity:
Application (client) ID : 14b78153-0017-41fb-a1ee-0cd4e9d7082a
Using the Code
In order to use this code sample, you need to update the authentication
object with the values collected in the previous steps like so:
var authentication = new
{
Authority = "https://graph.microsoft.com",
Directory = "4999ebad-131b-49f8-836b-cfe343676765",
Application = "14b78153-0017-41fb-a1ee-0cd4e9d7082a",
ClientSecret = "y3Dk3SfKa[XtK46SvET@C:vrUxt.uDF2"
};
Now you are ready to create your first Microsoft Graph query in a few simple steps.
First, you will need to create a new C# Console Application in Visual Studio and in the NuGet packet manager, add Microsoft.Graph
and Microsoft.Identity.Client
to your project.
Create the following static
method in your Program
class:
private static async Task CallWebApi()
{
var authentication = new
{
Authority = "https://graph.microsoft.com",
Directory = "4999ebad-131b-49f8-836b-cfe343676765",
Application = "14b78153-0017-41fb-a1ee-0cd4e9d7082a",
ClientSecret = "y3Dk3SfKa[XtK46SvET@C:vrUxt.uDF2"
};
var app = ConfidentialClientApplicationBuilder.Create(authentication.Application)
.WithClientSecret(authentication.ClientSecret)
.WithAuthority(AzureCloudInstance.AzurePublic, authentication.Directory)
.Build();
var scopes = new [] { "https://graph.microsoft.com/.default" };
var authenticationResult = await app.AcquireTokenForClient(scopes)
.ExecuteAsync();
var graphServiceClient = new GraphServiceClient(
new DelegateAuthenticationProvider(x =>
{
x.Headers.Authorization = new AuthenticationHeaderValue(
"Bearer", authenticationResult.AccessToken);
return Task.FromResult(0);
}));
var users = await graphServiceClient.Users.Request().GetAsync();
foreach (var user in users)
Console.WriteLine(user.DisplayName);
}
And finally, update your Main
function like so:
static void Main(string[] args)
{
try
{
CallWebApi().Wait();
}
catch (MsalUiRequiredException)
{
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
}
}
You should be good to go, execute the program and a list of all users in your Azure AD should scroll by on the screen.
I hope you found this article helpful in dealing with the complexities with Azure configuration and authentication.
Advanced Examples
Once you get Microsoft Graph to respond, half the battle is won. Actually, getting the information you require is another topic in itself. To get you going, I have added some examples that may be useful.
Selecting Properties
When querying Microsoft Graph using the Graph Service Client, you will get a nice object in return, but you will soon realize that many properties are null
even though they have values in your Azure Active Directory. A good example for this is the Department
property on an AAD User. Using the Select
statement will add these properties to your result.
var users = await graphServiceClient
.Users
.Request()
.Select(user => new
{
user.Id
user.UserPrincipalName,
user.DisplayName,
user.GivenName,
user.Surname,
user.Department,
user.Mail,
})
.GetAsync();
Expanding Collections
Collections such as the MemberOf
collection on an AAD User will not be returned even if they are Selected as in the previous example. Here is an example of how to query the MemberOf
collection to find group membership, provided you have fetched the User
first.
var memberOf = graphServiceClient.Users[user.Id].MemberOf.Request().GetAsync();
while (memberOf != null)
{
foreach (var directoryObject in memberOf.Result.CurrentPage)
{
if (!(directoryObject is Group group)) continue;
Console.WriteLine(group.DisplayName);
}
memberOf = memberOf.Result.NextPageRequest?.GetAsync();
}
RAW Queries
You can use the Graph Service Client to manage your security tokens but run your own raw queries like this:
var memberOf = await graphServiceClient.HttpProvider
.SendAsync(new HttpRequestMessage(HttpMethod.Get,
$"https://graph.microsoft.com/v1.0/users/{user.Id}/memberOf"));
var responseStream = memberOf.Content.ReadAsStreamAsync();
using (var reader = new StreamReader(responseStream.Result))
{
while (!reader.EndOfStream)
{
Console.WriteLine(reader.ReadLine());
}
}
History
- 30th October, 2019: Initial version
- 4th November, 2019: Added a few examples