Exercise 1: Working with users in the organization

In this exercise, you’ll create an Azure AD application registration using the Azure Active Directory admin center, a .NET Core console application, and query Microsoft Graph for user data.

Prerequisites

Developing Microsoft Graph apps requires a Microsoft 365 tenant.

For the Microsoft 365 tenant, follow the instructions on the Microsoft 365 Developer Program site for obtaining a developer tenant if you don’t currently have a Microsoft 365 account.

You’ll use the .NET SDK to create custom Microsoft Graph app in this module. The exercises in this module assume you have the following tools installed on your developer workstation.

[!IMPORTANT] In most cases, installing the latest version of the following tools is the best option. The versions listed here were used when this module was published and last tested.

You must have the minimum versions of these prerequisites installed on your workstation.

Task 1: Create an Azure AD application

  1. Open a browser and navigate to the Azure Active Directory admin center (https://aad.portal.azure.com). Sign in using a Work or School Account that has global administrator rights to the tenancy.

  2. Select Azure Active Directory in the left-hand navigation.

  3. Select Manage > App registrations in the left-hand navigation.

Screenshot of the App registrations

  1. On the App registrations page, select New registration.

Screenshot of App Registrations page

  1. On the Register an application page, set the values as follows:
  • Name: Graph Console App
  • Supported account types: Accounts in this organizational directory only (Contoso only - Single tenant)

    Screenshot of the Register an application page

  1. Select Register.

  2. On the Graph Console App page, copy the value of the Application (client) ID and Directory (tenant) ID; you’ll need these in the application.

Screenshot of the application ID of the new app registration

  1. Select Manage > Authentication.

  2. In the Platform configurations section, select the Add a platform button. Then in the Configure platforms panel, select the Mobile and desktop applications button:

Screenshot of the Platform configurations section

  1. In the Redirect URIs section of the Configure Desktop + devices panel, select the checkbox that ends with nativeclient, set Custom redirect URIs to http://localhost, and then select the Configure button:

Screenshot of the Configure Desktop + devices panel

Grant Azure AD application permissions to Microsoft Graph

After creating the application, you need to grant it the necessary permissions to Microsoft Graph.

  1. Select API Permissions in the left-hand navigation panel.

Screenshot of the API Permissions navigation item

  1. Select the Add a permission button.

  2. In the Request API permissions panel that appears, select Microsoft Graph from the Microsoft APIs tab.

Screenshot of Microsoft Graph in the Request API permissions panel

  1. When prompted for the type of permission, select Delegated permissions.

  2. Enter User.R in the Select permissions search box and select the User.Read.All permission, followed by the Add permission button at the bottom of the panel.

Screenshot of the User.Read.All permission in the Request API permissions panel

  1. In the Configured Permissions panel, select the button Grant admin consent for [tenant], and then select the Yes button in the consent dialog to grant all users in your organization this permission.

[!NOTE] The option to Grant admin consent in the Azure AD admin center simplifies the exercise by pre-consenting the permissions to the users in the tenant.

Task 2: Create .NET Core console application

  1. Open your command prompt, navigate to a directory where you have rights to create your project, and run the following command to create a new .NET Core console application:
dotnet new console -o graphconsoleapp
  1. After creating the application, run the following commands to ensure your new project runs correctly:
cd graphconsoleapp
dotnet nuget add source --name nuget.org https://api.nuget.org/v3/index.json
dotnet add package Microsoft.Identity.Client
dotnet add package Microsoft.Graph
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.FileExtensions
dotnet add package Microsoft.Extensions.Configuration.Json

[!NOTE] Be sure to confirm that each package is successfully installed before proceeding.

  1. Open the application in Visual Studio Code using the following command:
code .
  1. If Visual Studio code displays a dialog box asking if you want to add required assets to the project, select Yes.

Update the console app to enable nullable reference types

Nullable reference types refer to a group of features introduced in C# 8.0 that you can use to minimize the likelihood that your code causes the runtime to throw System.NullReferenceException.

Nullable reference types are enabled by default in .NET 6 projects, they’re disabled by default in .NET 5 projects.

Ensuring that nullable reference types are enabled isn’t related to the use of Microsoft Graph, it just ensures the exercises in this module can contain a single set of code that will compile without warnings when using either .NET 5 or .NET 6.

Open the graphconsoleapp.csproj file and ensure the <PropertyGroup> element contains the following child element:

<Nullable>enable</Nullable>

Update the console app to support Azure AD authentication

  1. Create a new file named appsettings.json in the root of the project and add the following code to it:
{
  "tenantId": "YOUR_TENANT_ID_HERE",
  "applicationId": "YOUR_APP_ID_HERE"
}
  1. Update properties with the following values:
  • YOUR_TENANT_ID_HERE: Azure AD directory ID
  • YOUR_APP_ID_HERE: Azure AD client ID

Create helper class

  1. Create a new folder Helpers in the project.

  2. Create a new file MsalAuthenticationProvider.cs in the Helpers folder and add the following code:

using System.Net.Http.Headers;
using Microsoft.Identity.Client;
using Microsoft.Graph;

namespace Helpers
{
  public class MsalAuthenticationProvider : IAuthenticationProvider
  {
    private static MsalAuthenticationProvider? _singleton;
    private IPublicClientApplication _clientApplication;
    private string[] _scopes;
    private string? _userId;

    private MsalAuthenticationProvider(IPublicClientApplication clientApplication, string[] scopes)
    {
      _clientApplication = clientApplication;
      _scopes = scopes;
      _userId = null;
    }

    public static MsalAuthenticationProvider GetInstance(IPublicClientApplication clientApplication, string[] scopes)
    {
      if (_singleton == null)
      {
        _singleton = new MsalAuthenticationProvider(clientApplication, scopes);
      }

      return _singleton;
    }

    public async Task AuthenticateRequestAsync(HttpRequestMessage request)
    {
      var accessToken = await GetTokenAsync();

      request.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
    }

    public async Task<string> GetTokenAsync()
    {
      if (!string.IsNullOrEmpty(_userId))
      {
        try
        {
          var account = await _clientApplication.GetAccountAsync(_userId);

          if (account != null)
          {
            var silentResult = await _clientApplication.AcquireTokenSilent(_scopes, account).ExecuteAsync();
            return silentResult.AccessToken;
          }
        }
        catch (MsalUiRequiredException) { }
      }

      var result = await _clientApplication.AcquireTokenInteractive(_scopes).ExecuteAsync();
      _userId = result.Account.HomeAccountId.Identifier;
      return result.AccessToken;
    }
  }
}

Incorporate Microsoft Graph into the console app

  1. Open the Program.cs file and replace the entire contents with the following code:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using Microsoft.Graph;
using Microsoft.Extensions.Configuration;
using Helpers;

namespace graphconsoleapp
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}
  1. Add the following method LoadAppSettings to the Program class. The method retrieves the configuration details from the appsettings.json file previously created:
private static IConfigurationRoot? LoadAppSettings()
{
  try
  {
    var config = new ConfigurationBuilder()
                      .SetBasePath(System.IO.Directory.GetCurrentDirectory())
                      .AddJsonFile("appsettings.json", false, true)
                      .Build();

    if (string.IsNullOrEmpty(config["applicationId"]) ||
        string.IsNullOrEmpty(config["tenantId"]))
    {
      return null;
    }

    return config;
  }
  catch (System.IO.FileNotFoundException)
  {
    return null;
  }
}
  1. Add the following method CreateAuthorizationProvider to the Program class. The method will create an instance of the clients used to call Microsoft Graph.
private static IAuthenticationProvider CreateAuthorizationProvider(IConfigurationRoot config)
{
  var clientId = config["applicationId"];
  var authority = $"https://login.microsoftonline.com/{config["tenantId"]}/v2.0";

  List<string> scopes = new List<string>();
  scopes.Add("https://graph.microsoft.com/.default");

  var cca = PublicClientApplicationBuilder.Create(clientId)
                                          .WithAuthority(authority)
                                          .WithDefaultRedirectUri()
                                          .Build();
  return MsalAuthenticationProvider.GetInstance(cca, scopes.ToArray());
}
  1. Add the following method GetAuthenticatedGraphClient to the Program class. The method creates an instance of the GraphServiceClient object.
private static GraphServiceClient GetAuthenticatedGraphClient(IConfigurationRoot config)
{
  var authenticationProvider = CreateAuthorizationProvider(config);
  var graphClient = new GraphServiceClient(authenticationProvider);
  return graphClient;
}
  1. Locate the Main method in the Program class. Add the following code to the end of the Main method to load the configuration settings from the appsettings.json file:
var config = LoadAppSettings();
if (config == null)
{
  Console.WriteLine("Invalid appsettings.json file.");
  return;
}
  1. Add the following code to the end of the Main method, just after the code added in the last step. This code will obtain an authenticated instance of the GraphServiceClient:
var client = GetAuthenticatedGraphClient(config);
  1. Add the following code to request all users from the current organization and write them to the console.
// request 1 - all users
var requestAllUsers = client.Users.Request();

var results = requestAllUsers.GetAsync().Result;
foreach (var user in results)
{
  Console.WriteLine(user.Id + ": " + user.DisplayName + " <" + user.Mail + ">");
}

Console.WriteLine("\nGraph Request:");
Console.WriteLine(requestAllUsers.GetHttpRequestMessage().RequestUri);

Build and test the application

  1. Run the following command in a command prompt to ensure the developer certificate has been trusted:
dotnet dev-certs https --trust
  1. Run the following command in a command prompt to compile the console application:
dotnet build
  1. Run the following command to run the console application:
dotnet run

You now need to authenticate with Azure Active Directory. A new tab in your default browser should open to a page asking you to sign-in. After you’ve logged in successfully, you’ll be redirected to a page displaying the message, “Authentication complete. You can return to the application. Feel free to close this browser tab”. You may now close the browser tab and switch back to the console application.

  1. The application will write information about all users in the organization to the console:

Screenshot of the console application showing all users in the organization

Task 3: Display the currently signed in user’s details

Now, update the console app to show details on the current user.

  1. Locate the code you added above for // request 1 - all users and comment it out so it doesn’t continue to execute.

  2. Add the following code to the Main method of the console application. This will get and display the details of the currently signed in user:

// request 2 - current user
var requestMeUser = client.Me.Request();

var resultMe = requestMeUser.GetAsync().Result;
Console.WriteLine(resultMe.Id + ": " + resultMe.DisplayName + " <" + resultMe.Mail + ">");

Console.WriteLine("\nGraph Request:");
Console.WriteLine(requestMeUser.GetHttpRequestMessage().RequestUri);

Build and test the application

  1. Run the following command in a command prompt to compile and run the console application:
dotnet build
dotnet run
  1. After you’ve logged in, you’ll see the details of the signed in user written to the console.

Screenshot of the console application showing the signed in user

Task 4: Display details of a specific user

In this last section, you’ll learn how to obtain a specific user’s details.

  1. Locate the code you added above for // request 2 - current user and comment it out so it doesn’t continue to execute.

The first step is finding a specific user’s unique identifier in your organization. From the first example above, copy the Id of a user in your organization other than the one that is currently signed in.

  1. Add the following code to the Main method of the console application. This will obtain the details of a specific user:
// request 3 - specific user
var requestSpecificUser = client.Users[""].Request();
var resultOtherUser = requestSpecificUser.GetAsync().Result;
Console.WriteLine(resultOtherUser.Id + ": " + resultOtherUser.DisplayName + " <" + resultOtherUser.Mail + ">");

Console.WriteLine("\nGraph Request:");
Console.WriteLine(requestSpecificUser.GetHttpRequestMessage().RequestUri);
  1. Update the `` string with the Id of an existing user you copied previously. Notice that this code will get a specific user by passing in their Id into the Users collection.

Build and test the application

  1. Run the following command in a command prompt to compile and run the console application:
dotnet build
dotnet run
  1. After you’ve logged in, you’ll see the details of the user you selected.

Screenshot of the console application showing a specific user

Summary

In this exercise, you created an Azure AD application registration using the Azure Active Directory admin center, a .NET Core console application, and query Microsoft Graph for user data.