Exercise 1: Working with groups 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 details on Office 365 groups.

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.ReadBasic.All permission. Repeat the process to add the permission Group.Read.All. Then select the Add permission button at the bottom of the panel to add the permissions to the app.

  3. 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. Replace the contents of the Main method with the following code that loads 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 the end of the Main method, just after the code added in the last step. This code will submit a request for the current user’s profile so it can display a welcome message to the user:
var profileResponse = client.Me.Request().GetAsync().Result;
Console.WriteLine("Hello " + profileResponse.DisplayName);
  1. Next, add the following code to the end of the Main method. This code will request all the Office 365 groups in the current tenant and write them to the console:
// request 1 - all groups
Console.WriteLine("\n\nREQUEST 1 - ALL GROUPS:");
var requestAllGroups = client.Groups.Request();
var resultsAllGroups = requestAllGroups.GetAsync().Result;
foreach (var group in resultsAllGroups)
{
  Console.WriteLine(group.Id + ": " + group.DisplayName + " <" + group.Mail + ">");
}

Console.WriteLine("\nGraph Request:");
Console.WriteLine(requestAllGroups.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 the data returned from the request for all groups in the organization to the console.

Screenshot of the console application showing all groups in the organization

Task 3: Get a specific Office 365 group

In this section, you’ll get a specific group using Microsoft Graph.

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

  2. Using the results in the console from the previous step, copy the ID from one of the groups displayed. Add the following code to the end of the Main method, replacing `` with the ID you copied from the console.

var groupId = "";
  1. Next, add the following code to the end of the Main method. This code will request a specific group and write its details to the console:
// request 2 - one group
Console.WriteLine("\n\nREQUEST 2 - ONE GROUP:");
var requestGroup = client.Groups[groupId].Request();
var resultsGroup = requestGroup.GetAsync().Result;
Console.WriteLine(resultsGroup.Id + ": " + resultsGroup.DisplayName + " <" + resultsGroup.Mail + ">");

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

Build and test the application

  1. Run the following commands 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 results of a single group with the ID you specified written to the console.

Screenshot of the console application showing a single group in the organization

Task 4: Get owners of an Office 365 group

In this section, you’ll get the owner of the group you obtained in the last section.

  1. Locate the code you added above for // request 2 - one group and comment it out so it doesn’t continue to execute. Don’t comment out the declaration of the groupId variable.

  2. Add the following code to the end of the Main method. This will get the collection of owners of the specified group and write them to the console:

// request 3 - group owners
Console.WriteLine("\n\nREQUEST 3 - GROUP OWNERS:");
var requestGroupOwners = client.Groups[groupId].Owners.Request();
var resultsGroupOwners = requestGroupOwners.GetAsync().Result;
foreach (var owner in resultsGroupOwners)
{
  var ownerUser = owner as Microsoft.Graph.User;
  if (ownerUser != null)
  {
    Console.WriteLine(ownerUser.Id + ": " + ownerUser.DisplayName + " <" + ownerUser.Mail + ">");
  }
}

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

[!NOTE] Owners are currently not available in Microsoft Graph for groups that were created in Exchange or groups that are synchronized from an on-premises environment. If no owners are displayed, it’s likely you selected a one of these types of group. Update the code to use a different group ID and rerun the test. Repeat this process until until at least one owner is displayed.

Build and test the application

  1. Run the following commands 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 list of owners of a single group with the ID you specified written to the console.

Screenshot of the console application showing a single group's owners in the organization

Task 5: Get members of an Office 365 group

In this section, you’ll get all the members of the group you obtained in a previous section.

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

  2. Add the following code to the end of the Main method. This will get the collection of members of the specified group and write them to the console:

// request 4 - group members
Console.WriteLine("\n\nREQUEST 4 - GROUP MEMBERS:");
var requestGroupMembers = client.Groups[groupId].Members.Request();
var resultsGroupMembers = requestGroupMembers.GetAsync().Result;
foreach (var member in resultsGroupMembers)
{
  var memberUser = member as Microsoft.Graph.User;
  if (memberUser != null)
  {
    Console.WriteLine(memberUser.Id + ": " + memberUser.DisplayName + " <" + memberUser.Mail + ">");
  }
}

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

Build and test the application

  1. Run the following commands 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 list of members of a single group with the ID you specified written to the console.

Screenshot of the console application showing a single group's members in the organization

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 details on Office 365 groups.