Using Microsoft Graph API to interact with Azure AD

In my last article, I showed how to authenticate on Azure AD using a user name / password without using the native web flow.

The underlying scenario was to migrate an application using an LDAP server by leveraging an Azure AD tenant.

The logical continuation of that scenario is to use the Microsoft Graph API to interact with the tenant the same way we would use LDAP queries to interact with the LDAP server.

Microsoft Graph API is a generalization of the Azure AD Graph API and should be used instead.  It consists of simple REST queries which are all documented.

In this scenario, I’ll consider three simple interactions:

But first we need to setup the Azure AD tenant.

Azure AD setup

We’re going to rely on the last article to do the heavy lifting.

We are going to create a new application (here we’re going to use the name “QueryingApp”) of type Web App / API (although native should probably work).

The important part is to grab its Application-ID & also to give it enough permission to create users.


In this scenario, the application is going to authenticate itself (as opposed to a user) so we need to define a secret.


We’ll need to add a key, save & copy the key value.

Authenticating with ADAL

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

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

        private static async Task<string> AppAuthenticationAsync()
            //  Constants
            var tenant = "";
            var resource = "";
            var clientID = "9a9f5e70-5501-4e9c-bd00-d4114ebeb419";
            var secret = "Ou+KN1DYv8337hG8o8+qRZ1EPqBMWwER/zvgqvmEe74=";

            //  Ceremony
            var authority = $"{tenant}";
            var authContext = new AuthenticationContext(authority);
            var credentials = new ClientCredential(clientID, secret);
            var authResult = await authContext.AcquireTokenAsync(resource, credentials);

            return authResult.AccessToken;

Here the clientID is the application ID of the application we created at secret is the secret key we created for it.

Here we return the access token as we’re going to use them.

Authenticating with HTTP POST

If we do not want to integrate with the ADAL, here’s the bare bone HTTP post version:

        private static async Task<string> HttpAppAuthenticationAsync()
            //  Constants
            var tenant = "";
            var clientID = "9a9f5e70-5501-4e9c-bd00-d4114ebeb419";
            var resource = "";
            var secret = "Ou+KN1DYv8337hG8o8+qRZ1EPqBMWwER/zvgqvmEe74=";

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

                requestParameters.Add("resource", resource);
                requestParameters.Add("client_id", clientID);
                requestParameters.Add("grant_type", "client_credentials");
                requestParameters.Add("client_secret", secret);

                var url = $"{tenant}/oauth2/token";
                var responsebytes = await webClient.UploadValuesTaskAsync(url, "POST", requestParameters);
                var responsebody = Encoding.UTF8.GetString(responsebytes);
                var obj = JsonConvert.DeserializeObject<JObject>(responsebody);
                var token = obj["access_token"].Value<string>();

                return token;

Here I use the popular Newtonsoft Json Nuget Package to handle JSON.

By no mean is the code here a master piece of robustness and style.  It is meant to be straightforward and easy to understand.  By all means, improve it %500 before calling it production ready!

Testing if a user exists

Here we’re going to use Get a User of Microsoft Graph API.

There is actually a NuGet package for Microsoft Graph API and, in general SDKs (at the time of this writing) for 9 platforms.

        private static async Task<bool> DoesUserExistsAsync(HttpClient client, string user)
                var payload = await client.GetStringAsync($"{user}");

                return true;
            catch (HttpRequestException)
                return false;

Again, the code is minimalist here.  The HTTP GET actually returns user information that could be used.

Returning the groups a user belong to

Here we’re going to use the memberof method of Microsoft Graph API.

        private static async Task<string[]> GetUserGroupsAsync(HttpClient client, string user)
            var payload = await client.GetStringAsync(
            var obj = JsonConvert.DeserializeObject<JObject>(payload);
            var groupDescription = from g in obj["value"]
                                   select g["displayName"].Value<string>();

            return groupDescription.ToArray();

Here, we deserialize the returned payload to extract the group display names.  The information returned is richer and could be used.

Creating a new user

Finally we’re going to use the Create User method of Microsoft Graph API.

This is slightly more complicated as it is an HTTP POST with a JSON payload in input.

        private static async Task CreateUserAsync(HttpClient client, string user, string domain)
            using (var stream = new MemoryStream())
            using (var writer = new StreamWriter(stream))
                var payload = new
                    accountEnabled = true,
                    displayName = user,
                    mailNickname = user,
                    userPrincipalName = $"{user}@{domain}",
                    passwordProfile = new
                        forceChangePasswordNextSignIn = true,
                        password = "tempPa$$w0rd"
                var payloadText = JsonConvert.SerializeObject(payload);

                stream.Position = 0;

                using (var content = new StreamContent(stream))
                    content.Headers.Add("Content-Type", "application/json");

                    var response = await client.PostAsync("", content);

                    if (!response.IsSuccessStatusCode)
                        throw new InvalidOperationException(response.ReasonPhrase);

Calling Code

The calling code looks like this:

        private static async Task Test()
            //var token = await AppAuthenticationAsync();
            var token = await HttpAppAuthenticationAsync();

            using (var client = new HttpClient())
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

                var user = "";
                var userExist = await DoesUserExistsAsync(client, user);

                Console.WriteLine($"Does user exists?  {userExist}");

                if (userExist)
                    var groups = await GetUserGroupsAsync(client, user);

                    foreach (var g in groups)
                        Console.WriteLine($"Group:  {g}");

                    await CreateUserAsync(client, "newuser", "");


We can see that using the Microsoft Graph API, most if not all LDAP query can easily be converted.

Microsoft Graph API is aligned with OData v3 which makes it a great REST API where filtering queries are standardized.

19 responses

  1. Anonymous 2017-04-27 at 06:11

    Thanks for posting this, it really saved my bacon!. I ran into too many issues when trying to remove users from groups using the .Net API. It just wouldn’t work. This works like a champ for that.

  2. Vincent-Philippe Lauzon 2017-04-27 at 06:13

    Excellent! Tx you.

  3. davalmo 2017-08-25 at 14:13

    Hi ,your post is very interesting, I already did all the steps, I actually get a token but I do not understand when I use the microsoft graph api to upload a file is not working, in the AuthContext I only see that it gets the token, but not the user information or one account when save the file.

    also create a console application and a web aplication and two Azure Aplications With respect to the previous article but i think this applications dont work together.

  4. Vincent-Philippe Lauzon 2017-08-30 at 14:05

    What API do you use to upload a file?

  5. Noor Elahi 2017-10-20 at 03:40

    Great buddy. Thanks

  6. mohammad shahbaz khan 2017-12-15 at 20:51

    await call stay forever when I check DoesUserExists in line await DoesUserExistsAsync(client, user);

  7. shahbazkhanweb 2017-12-15 at 20:52

    await call stay forever at line await DoesUserExistsAsync(client, user);

  8. shahbazkhanweb 2017-12-15 at 21:01

    this line takes forever: var payload = await client.GetStringAsync($”{user}”);

  9. Vincent-Philippe Lauzon 2017-12-16 at 06:41

    Is it possible that you are running that code within an old version of ASP.NET?

    I remember a colleague having issues with async code awaiting for an HTTP call and the issue was a bug in old versions of ASP.NET. Something in the win32 threading mechanism that left the code hanging.

  10. Panduka Weerasekara 2018-07-15 at 11:50

    Hi your tutorial is very help full , but i have a question that i am currently creating MVC web app and i want show all the users in the in the view, so do you have any idea of the code to get the header with the token to show the all the users in the tenet , your help will be highly appreciated ,

  11. Vincent-Philippe Lauzon 2018-07-18 at 08:04

    You want to list all the users in the tenant?

  12. Wil Bloodworth 2018-10-11 at 14:47

    The moved the docs (shocker!). Here’s the new URL for Get User:

  13. Vincent-Philippe Lauzon 2018-10-12 at 07:05

    Hi Wil.

    Thanks for the tip! I fixed 3 broken links (including the one you mentioned). Let me know if you find any others.

  14. Eugene 2019-07-21 at 03:58

    Hi! Thanks a lot for HTTP POST auth example.

  15. Lekha Nair 2019-08-26 at 06:59

    Hi, Is there a way to get the user info by email?

  16. Vincent-Philippe Lauzon 2019-08-26 at 13:01

    I’m not sure I get the question… it’s an API so the info comes back as the request’s response.

  17. Nitin 2020-08-06 at 12:51

    Hi, My requirment is create teams online meeting event using mvc application without Microsoft log-in page … Plz help me

  18. Vincent-Philippe Lauzon 2020-08-10 at 10:00

    Hi Nitin,

    I’m really no expert in O365 but what I’ve seen customer doing in that type of scenario is to use a separate user account to interact with O365. O365 doesn’t support service principals (to my knowledge), so it needs to be a “real user” account. Typically customers create a dummy user account using some field / nomenclature to specify it isn’t bound to a real person.

    So you have your MVC app that has its own authentication scheme going on and then it uses that user to interact with O365. Quite a bit like a web app using a service principal / SQL user to interact with a SQL DB.

  19. Sam 2021-08-27 at 07:31

    Thanks buddy, this was exactly what I was after, great work, nice and simple

Leave a comment