Intro to the Microsoft Graph .NET Client Library

A month or so ago, the Microsoft Graph .NET Client Library was released.  Working with the Graph client has largely been direct web requests up until now, so the client library is a welcome addition.  However, as I started to explore the library, I discovered that finding documentation was a bit challenging.  This is a basic walkthrough of the client library to help people to get started with their first calls.


The Graph .NET Client Library is intended to be very extensible and work in a variety of situations.  For this first introduction, we’ll just use Azure Active Directory and ADAL to authenticate ourselves into the graph.  I’ve written about the AAD/ADAL process before, so instead of re-writing it now, you can follow the walkthrough here:  Jonathan Huss – The Help Desk demo, Part 2 – Azure Active Directory.  For the client library, we don’t need a certificate for authentication.  We can just use a basic client id and client secret authentication model.  The first part of this post describes how to generate the client id and client secret:  Jonathan Huss – Getting started with the Azure Active Directory Graph Client Library.  So, be sure that you’ve created your application with appropriate permissions in Azure and have the client id and client secret available.

Getting the bits

I’m just using a standard console app project for this demo.  We need to download the Graph .NET Client Library bits from NuGet into our project.  The NuGet package that we’re going to download is “Microsoft.Graph”:


We’ll also need to install “Microsoft.IdentityModel.Clients.ActiveDirectory”.  This is commonly known as ADAL or the Active Directory Authentication Library:



The first thing that we’ll do is to create a GraphServiceClient.  To do so, we need to tell the Graph Client Library how we want to authenticate.  In this case, we’re using Azure as the authentication source and ADAL to handle the OAuth flow.  The way that we tell the Graph Client Library to use Azure and ADAL is actually via the GraphServiceClient constructor itself, using the IAuthenticationProvider parameter:


As far as I know, there aren’t any pre-built AuthenticationProvider classes, so we’ll need to go create our own to work against Azure.  This is actually sort of handy, since we could build whatever we needed if we were using some other kind of authentication, although some pre-built providers for known authentication sources would be convenient. 

The first thing we need to do is to create our own AzureAuthenticationProvider class that implements the IAuthenticationProvider interface.  When we do that, we discover that there is only one function, AuthenticateRequestAsync:


What in the world should we do in that function?  Well, if you’ve ever worked against Azure/O365 services before (or any OAuth service, really), you likely know that to authenticate to the service, you need to send an Authorization header that includes the Bearer token (commonly known as the access token).  That’s precisely what we’re going to do in this function.  We’re going to provide authentication details to the request.  The idea is that when the library sends the request, it passes through this function and provides us an opportunity to inject our Bearer token into that request. 

Before we can pass the access token as part of the request, we need to acquire the access token.  We’ll do that just like we always have in the past.  You can find a walkthough toward the end of this post:  Jonathan Huss – Getting Started with Azure Active Directory Graph Client Library.  Our finished code looks like this:

class AzureAuthenticationProvider : IAuthenticationProvider
    public async Task AuthenticateRequestAsync(HttpRequestMessage request)
        string clientId = "ae798feb-2a57-4738-8037-2e7d57ac6930";
        string clientSecret = "84fxdktLxiXvax0iI/m1ARB+QaEpd2c8jZD6tQK9Alc=";

        AuthenticationContext authContext = new AuthenticationContext("");

        ClientCredential creds = new ClientCredential(clientId, clientSecret);

        AuthenticationResult authResult = await authContext.AcquireTokenAsync("", creds);

        request.Headers.Add("Authorization", "Bearer " + authResult.AccessToken);

This function reaches out to the authority, passes our client id and client secret along with our resource identifier, and requests our token.  Once the token has been received, it’s injected into the Authorization header with the Bearer prefix.  For the sake of making this fairly clear and concise, there’s no storage or refreshing of the token, nor are there any Settings, ConfigurationManager, or token cache implementations.  There’s also no error handling.  Certainly in a production environment, you’d want to incorporate those components.

Now that we have our AzureAuthenticationProvider all built out, we just need to pass it to the GraphServiceClient via the constructor, like so:

GraphServiceClient client = new GraphServiceClient(new AzureAuthenticationProvider());

Piece of cake right?  Yep.

Note:  This is an app-only authentication model.  The token acquisition steps are slightly different for a delegated authentication model, but can be found in numerous places on the Internet, such as

Retrieving some data

Now that we have our client all setup, let’s see if we can retrieve some data.  There are quite a few properties on the client object that correspond to the Graph URL segments (documentation on URL segments here: 

Maybe we’d like to create a function to look up a user, something like this:

public async Task<User> GetUser(string userPrincipalName)
    GraphServiceClient graphClient = new GraphServiceClient(new AzureAuthenticationProvider());
    User user = await graphClient.Users[userPrincipalName].Request().GetAsync();
    return user;

If we run that with a breakpoint, we can see that, in fact, it does retrieve the requested user, which is sort of convenient that it works as anticipated.


What if we wanted to search for all of the users that have a last name that starts with some value, “Hu”, for example, which should provide us with all of the Husses, Hubbards, Huffmans, etc.  Sure, we can do that using the Filter function (which results in an OData $filter parameter), like so:


When sending a query, the default maximum result size is 100 records.  What if we want to return more than that by using the OData $top parameter?  Yep, that works too (requesting 500 users, in this example):


Alternatively, we could use the .Top() function from the Request in place of the $top parameter:


Also, in the last two examples, we note that “NextPageRequest” is populated.  This property tells us that there are more pages to be retrieved.  If we want to retrieve all of the pages at once, we just need to iterate on that NextPageRequest property, like so:


The Graph Client Library has quite a few objects available for interaction.  At least as of the current version of the Graph Client Library (v1.0.1 on 5/24/2016), the available objects are as follows.  I certainly expect this to grow as the Graph itself grows.



There is quite a bit more that we can talk about regarding the Graph Client Library.  I plan to write a follow up post that describes more of the functionality.  Definitely comment and let me know what would be useful for you and I’ll try to include it.  Hopefully, though, this is a good starting point to get folks past the “How in the world do I get started with the new Graph Client Library?!?” question.


20 comments on “Intro to the Microsoft Graph .NET Client Library

  1. Thanks for this article, I was struggling to find meaningful guide and resources for ClientCredential Auth with Microsoft Graph. Your article explains this topic very well. Really appreciate it!

  2. This guide is so simple and easy to use. I have a small query hope you can help me. I am trying to access the photo of a user, but I am unable to retrieve. I get rest of the details but no photo. Please help

      1. Hi Linto and Mani,

        Try something like this:

        Stream photoStream = await graphClient.Users[userPrincipalName].Photo.Content.Request().GetAsync();


  3. Great article. I’d make one minor tweak (and this is really minior)
    Your code:
    request.Headers.Add(“Authorization”, “Bearer ” + authResult.AccessToken);

    Use the Headers.Authorization property directly to avoid one more hard code (not real epic change):
    request.Headers.Authorization =
    new AuthenticationHeaderValue(“Bearer”, authResult.AccessToken);

    Trivial suggestion to a great article

  4. This and the one about creating an app in azure were a life saver but I do have a qustion.

    So following your setup here I can get connected to graph no problem and query the users for users but the problem is almost all the properties are null which isn’t very helpful.

    Do you have an incite on why that is or what we would need to do permission wise to make sure the application can access more information?

  5. Thank you so much for this post, really helps get even a sliver of understanding of the newer Graph API, especially regarding pulling more than 100 results from AAD!

    Merging your code with the pre-made code that comes with the ASP.NET MVC Web Application with Work/Organization sign on authentication was pretty straight forward too.

  6. WRT my last comment, I found a site that confirmed you need to use a different approach now with Shared Calendars:
    1. They must have been shared using the “new” approach in O365. If not, you need to deleted your shared calendars (as recipient), remove all the shares (as owner), then re-share thorugh the web portal.
    2. This will then enable the shared calendars to show up in your Me.Calendars.Request().GetAsync() call
    3. You can then use the id of the shared calendar to get more details, i.e. a view of the last year’s events:

    var startDate = new QueryOption(“StartDateTime”, DateTime.Now.AddYears(-1).ToString(“s”));
    var endDate = new QueryOption(“EndDateTime”, DateTime.Now.ToString(“s”));
    var options = new[]

    var lastYearsEvents = await graphClient.Me

  7. Hey again, while I was able to pull all users (including myself) using GraphServiceClient(new AzureAuthenticationProvider()).Users.Request().Top(500).GetAsync();

    I’m not able to get just myself using GraphServiceClient(new AzureAuthenticationProvider()).Me.Request().GetAsync();

    I asked on StackOverflow about this and was told I need to use “Authorization Code Flow”, would you (or anyone really) be able to help expand on this? Or maybe even show how to get the .Me functionality working?

    Thank you!

    1. Hi Ryan,

      The guidance you received is accurate. This demo connects to the Graph via an app-only flow. Basically, it’s connecting as an application rather than as a user. As such, /me/ isn’t really supported. If you want to use the /me/ construct, you’ll need to switch the authentication type to use a user based flow instead. More information here:


  8. trying to follow the guide but slightly confused.

    Where does GraphServiceClient graphClient = new GraphServiceClient(); go? What parameters go in it?

    From my understanding, it goes in the main function, no?

    1. Hi ZenunJ,

      The parameter for the GraphServiceClient is the authentication provider class. There’s a sample AzureAuthenticationProvider class in the post. Then, you can create a new instance of the Graph client anywhere that you need to make a call to Graph, including the main function, but also in other functions as well if need be.


  9. Hi Jonathan
    Thanks for this article. Do you know if the Microsoft.Graph querying specific fields? Looking through fields from the responses i’m getting, i can’t see specific fields i’m looking for. The User fields seems to be predetermined and does’t return all fields from Active directory.

  10. Hi Jonathan,

    i am trying to retrieve all the users from Azure Active Directory of my organization. I am newbie in dot net so please let me know if i need to write everything in a single C# script also how can i call it and save it in .csv file with all the required attributes for User info.

Leave a Reply

Your email address will not be published.