With the superannuation of AzureAD and the MSOnline module, Microsoft Graph API is the new direction for cloud computing. To maintain and configure Office 365 or Microsoft 365, admins must ensure they can link to Microsoft Graph API endpoints.

Using only a single REST API point (https://graph.microsoft.com), you can connect to any object in the Azure AD (Microsoft 365) tenant. You might believe it is only of interest to web developers, but this is not the case. Some Microsoft 365 data, objects, or resource properties can only be made available via Microsoft Graph. An Azure administrator must use Microsoft Graph to obtain analytic data, statistics, or other information.

This article will guide you through the steps necessary to connect to the Microsoft Graph API and manage Microsoft Office 365 with PowerShell.

Prerequisites

Downloading the Module

The first step in starting up with Using Microsoft Graph API in your Powershell session is to install the Microsoft.Graph Module. This module is much more widely called the Microsoft Graph Powershell SDK, and all of the cmdlets in it begin with “Mg.” Another thing I particularly appreciate about this module is that it works perfectly with Powershell 7.

Install-Module Microsoft.Graph

If the installation is successful, PowerShell returns no results. You can use the -Debug and -Verbose switches to get real-time information about the upload, download, and installation log.

To confirm the installation, run the following line

Get-Module -ListAvailable Microsoft.Graph
Installed Module
Installed Module

The Microsoft Graph API PowerShell Module contains several modules for managing Microsoft 365 and Office 365 services. When you download Microsoft.Graph module, these modules are set automatically. You can view them all if you run:

Get-Module -ListAvailable Microsoft.Graph*
All Graph PowerShell Modules

Office 365 is part of Microsoft 365 and to avoid keep mentioning Microsoft 365 and Office 365, I will mention Microsoft 365 which also applies to office 365.

Connect to Microsoft 365 Using PowerShell Graph SDK

The Graph supports two methods of connection.

  • Delegate: To connect, the user must enter a username and password.
  • Application: There is no need to write any username or password when using application authentication, which is primarily used during automation and background processes. Instead, authentication is accomplished through the use of Certificate-based authentication, Client Secret, or federated authentication.

The configuration settings for all of these methods are thoroughly explained in this tutorial. However, on whether to use Delegated or Application authentication, it is critical to use the correct scope when trying to connect to Microsoft Graph API.

Graph Explorer is a great starting point with a graphical user interface that is free and accessible online.

If you are new to Microsoft Graph, you can read more indepth about Graph Authentication and Permission scope in the following posts:
Connecting and Using Microsoft Graph API Using PowerShell
Migrate Your Script from AzureAD or MSOnline to Graph API

Using Graph Explorer To Find The Scope of a Cmdlet.

The scope is, in short, the way of telling Microsoft Graph that in this session, you need to do this and that, for example. You want to connect to the Azure Active Directory and read the user’s information. So while connecting to Microsoft Graph API, you need to pass User.Read.All. So how to find these scopes?

Graph Explorer helps find the scope and provides code snippets that help you know which cmdlet you need to use to do a certain task. Let’s take a look.

The Graph Explorer looks like this.

Graph Explorer

You don’t need to be an expert in Graph Explorer; for now, we need to know the basics. So to find the permission to read all Azure Active Directory user’s information:

  • Click on Resources
  • Scroll and search for Users
  • Click on GET users
  • Click on Modify Permission

Graph Explorer returns a list of all applicable permission that can be used to get all user’s information in the tenant.

You don’t need them all, just read the description and use the most suitable one. for this case, we need User.Read.All

Finding the required permissions.

You need to consent to the required permission to be granted. Simply click on Consent, and a new window appears which looks like the following.

Consent

The admin can click on Consent on behalf of your organization. This means that any user in the organization who accesses the application (in this case Graph Explorer) can access whatever the admin consent on behalf of the organization. For example, if an admin clicks on Consent on behalf of your organization when granting permission for User.Read.All, this permission is granted to all the users in the organization, and all users can connect to MS Graph API and run queries to read all the user’s information.

Always be sure only to use what you need and don’t click on Consent on behalf of your organization cause it’s easier.

Delegated Authentication To Connect To Microsft Office 365 Using Graph API

The most straightforward approach to managing Microsoft Office 365 is to connect to Graph API using delegated authentication. However, this approach necessitates the user authenticating each time the user wishes to connect. You’ll also need to know what scope to use, and you’ll be good to go.

  • Open PowerShell
  • Type the following Connect-MgGraph -scope @(‘User.Read.All’)
  • Enter the desired username and password.

You get a message Welcome To Microsoft Graph! You are now connected and can do whatever you specify in the scope. Give it a shot and see how it goes. Run Get-MgUser -All

PS C:\> Get-MgUser -All

Id                                   DisplayName  Mail                                       UserPrincipalName
--                                   -----------  ----                                       -----------------
6a5ec54c-5124-4116-ae6b-2a82ba061fec Faris Malaeb admin@powershellcenter2022.onmicrosoft.com admin@powershellcenter202…
3b02fdf3-ebc1-41ca-9d77-f36e4ff776f9 test1                                                   test1@powershellcenter202…

Application Authentication to Connect to Microsoft Office 365 Graph API

To configure a service and obtain a token from the Microsoft identity platform endpoint, follow these simple steps. The token can be used by your script to access Microsoft Graph with its own identity.

Here is a list of the required steps:

  • Registering Application in Azure Active Directory.
  • Create a Client Credentials (Client Secret or Certificate)
  • Add the required permission
  • Use the information from the previous steps in the PowerShell script.

Registering Application in Azure Active Directory

The Application registration process is a way of creating an identity SPN for your application, similar to a username. Tenant admin should register an application in Azure Active Directory by following these steps:

  • Open Azure Active Directory
  • Click on App Registrations.
  • Click on + New Registration
  • Type the application name you want.
  • Under the Supported Account Types, select Accounts in this organizational directory only (xxxxxxxxxx only – Single tenant).
  • Under the Redirect URI (Optional), type HTTP://localhost and select Public Client/Native (Mobile & Desktop)

The Redirect URI (optional) is the URI for where to send the authenticated user after successful authentication and authorization. The authorization server (Azure AD) sends the authorization code to the specified URI. since this is a local application, set the URI to be localhost. and click on Register

After completing the App Registration, The registered application property page opens, and here you find the following:

Registered App

Write down the Application (Client ID) and the Directory (Tenant) ID as these two values will be used in PowerShell to connect later.

Now that the application is registered, this process is similar to creating a username used to authenticate, but the credential part is still missing. I will cover in this post the Client Secret and Certificate-based authentication. You don’t need to configure both at your end. Just pick the one that suits you more.

Configure Azure Registered App to use Client Secret authentication

Client Secrets generate a long string with an expiration date. Consider the Client Secret a complex password string your script uses to connect to the cloud. However, the challenge with regular passwords remains the same: where and how to store them securely. You don’t want to hardcode the secret into your script because it’s a plain-text file, and having the secret hard-coded is akin to writing the password on your office screen. Anyone who uses the system will be able to see the credentials. This is one of the disadvantages of using Client Secret. Ensure that this string is securely fastened.

Click on New Client Secret, type a description, and specify an expiry period.

Client Secret

When you click Add, immediately write down the secret value of the key because you will never be able to see it again if you navigate away from this page, and you will have to create a new one. So keep it somewhere safe.

Secret Value

So the following are the main keys to remember and use in any PowerShell script that uses Application authentication with a Client Secret:

  • Tenant ID
  • Application ID (Client ID)
  • Secret Value

This concludes the authentication process. You can skip to the section Assigning Permission For the Registered app section.

Configure Azure Registered App to use Certificate-Based Authentication

Certificate authentication is more secure than Client Secret authentication. It is possible to use a self-signed certificate, but it is not recommended because:

  • Self-Signed Certificates are not generated by a trusted source, such as GeoTrust or the trusted CA of your local organization.
  • It is not revocable.
  • Inadequate visibility and control.

It is recommended that your certificate be generated by your certificate authority or obtained from a third-party certificate authority. But for now, I’ll show you how to use a Self-Signed Certificate.

I am not sure of the possibilty of using LetsEncrypte for such thing. I think it should work fine, if you try it let me know in the comments

According to what I’ve read, Microsoft isn’t verifying the domain name, certificate common name (CN), or certificate source, so the connection is fine and won’t generate any errors or warnings. The key, however, should be:

  • The key should be 2048 bits long.
  • It must employ RSA.
  • Signed using SHA256, SHA384, and SHA5120

To configure and store the certificate, run the PowerShell script below.

$CertParam = @{
    'KeyAlgorithm'      = 'RSA'
    'KeyLength'         = 2048
    'KeyExportPolicy'   = 'NonExportable'
    'DnsName'           = 'www.powershellcenter.com'
    'FriendlyName'      = 'My Application Authentication'
    'CertStoreLocation' = 'Cert:\CurrentUser\My\'
    'NotAfter'          = (Get-Date).AddYears(1)
}
$Cert = New-SelfSignedCertificate @CertParam
Export-Certificate -Cert $Cert -FilePath $Home\Desktop\AppAuthCert.cer

This generates and saves the certificate to your desktop as AppAuthCert.cer. The contents of the certificate are as follows.

Self-Signed Certificate

This certificate must be uploaded to the registered app in Azure Active Directory:

  • Navigate to Azure Active Directory
  • Select App Registrations
  • Look for the app that was created and click on it.
  • Select Certificates and Secrets
  • Select Certificates
Certificate Auth.

Click Upload Certificate, then navigate to and select the newly created certificate.

The Certificate thumbprint appears now under the certificates.

Adding Certificate

That’s all. The configurations are complete. Let’s give the application the necessary permissions.

Assigning Permission For the Registered app

Now we need to assign the application the permission scope it will use.

From the registered application page, click on API Permissions.

As a reminder, This application is intended to read all user’s data in the directory. The permission we need to assign for the application is User.Read.All. In the API Permission, follow these steps to add the permissions.

  • Click on Add a Permission
  • Select Microsoft Graph
  • Click Application Permissions
  • Type User.Read.All
  • Expand User and check on User.Read.All or whatever permission your application needs
  • Click Add Permissions
  • Click on Grant admin consent for Organzation_name

The status becomes green checked

API Permissions

Connecting to Microsoft Office 365 Graph API Using Client Secrets Authentication

Let’s combine all these pieces and connect to Microsoft Graph API using the registered application and Client Secret. Run the following code

$appid = 'cda60b52-9c53-47b0-909b-ebbb95839d1a'
$tenantid = '50b3efbf-f914-4286-b27c-0d7bb0148e56'
$secret = 'My_Secure_Value_That_I_Will_Keep_It_Safe'
 
$body =  @{
    Grant_Type    = "client_credentials"
    Scope         = "https://graph.microsoft.com/.default"
    Client_Id     = $appid
    Client_Secret = $secret
}
$ConnectionParameters=@{
    Uri="https://login.microsoftonline.com/$tenantid/oauth2/v2.0/token"
    Method ="POST"
    Body = $body
}
$connection = Invoke-RestMethod @ConnectionParameters
 
$token = $connection.access_token
Connect-MgGraph -AccessToken $token

By the way, you dont need to memorize all this code. but you need to understand the code strcuture

The result is a nice message Welcome To Microsoft Graph! To confirm the identity used, run Get-MgContext

ClientId              : cda60b52-9c53-47b0-909b-ebbb95839d1a
TenantId              : 50b3efbf-f914-4286-b27c-0d7bb0148e56
CertificateThumbprint : 
Scopes                : {User.Read.All}
AuthType              : UserProvidedAccessToken
AuthProviderType      : UserProvidedToken
CertificateName       : 
Account               : 
AppName               : Org-PowerShellCenter
ContextScope          : Process
Certificate           : 
PSHostVersion         : 2022.6.3
ClientTimeout         : 00:05:00

Take a look at the AppName and the scope. these are what was configured earlier.

Connecting to Microsoft Office 365 Using Certificate-Base Authentication

Now that we’ve covered creating the application, it’s important to remember that there are two ways to authenticate your freshly created application. These methods involve the use of a certificate or maybe a client secret. In this article, we’ll go over both methods, but we’ll start with certificates.

You can either use a self-signed certificate or perhaps a certificate from your PKI infrastructure with Azure. The more secure of these two options is your PKI infrastructure, but it’s comprehensible that not each environment has one. Because I do not have a PKI infrastructure throughout my lab, I’ll share the steps for utilizing a self-signed certificate.

The certificate authentication code is simpler.

$AppId = "cda60b52-9c53-47b0-909b-ebbb95839d1a"
$TenantId = "50b3efbf-f914-4286-b27c-0d7bb0148e56"
$Certificate = Get-ChildItem Cert:\CurrentUser\my\10CE6606C6605D2F6BE8E2237E3CA22215EAB70A # Self-Signed Certificate ThumbPrint
Connect-Graph -TenantId $TenantId -AppId $AppId -Certificate $Certificate

The outcome should also include a greeting to the msgraph API.

If you try to connect using any other certificate, you get the following error message

A configuration issue is preventing authentication – check the error message from the server for details. You can modify the configuration in the application registration portal. See https://aka.ms/msal-net-invalid-client for details. Original exception: AADSTS700027: The certificate with identifier used to sign the client assertion is not registered on application. [Reason – The key was not found., Thumbprint of key used by client: ‘16779462A0BAB49E88C304A77B464A6807F65F4D’, Please visit the Azure Portal, Graph Explorer or directly use MS Graph to see configured keys for app Id ‘cda60b52-9c53-47b0-909b-ebbb95839d1a’. Review the documentation at https://docs.microsoft.com/en-us/graph/deployments to determine the corresponding service endpoint and https://docs.microsoft.com/en-us/graph/api/application-get?view=graph-rest-1.0&tabs=http to build a query request URL, such as ‘https://graph.microsoft.com/beta/applications/cda60b52-9c53-47b0-909b-ebbb95839d1a’].
Trace ID: 0bb87fd6-f0df-4e8e-8993-8366221aae00
Correlation ID: 964622eb-eca1-47e3-8aa6-d9782e4de8ba
Timestamp: 2022-08-11 11:16:31Z

Running the Get-MgContext return the following

ClientId              : cda60b52-9c53-47b0-909b-ebbb95839d1a
TenantId              : 50b3efbf-f914-4286-b27c-0d7bb0148e56
CertificateThumbprint : 
Scopes                : {User.Read.All}
AuthType              : AppOnly
AuthProviderType      : ClientCredentialProvider
CertificateName       : 
Account               : 
AppName               : Org-PowerShellCenter
ContextScope          : Process
Certificate           : [Subject]
                          CN=www.powershellcenter.com
                        
                        [Issuer]
                          CN=www.powershellcenter.com
                        
                        [Serial Number]
                          2E1E3DD48DD6B08D4B493907597F93E8
                        
                        [Not Before]
                          11-Aug-22 2:37:58 PM
                        
                        [Not After]
                          11-Aug-23 2:47:58 PM
                        
                        [Thumbprint]
                          10CE6606C6605D2F6BE8E2237E3CA22215EAB70A
                        
PSHostVersion         : 2022.6.3
ClientTimeout         : 00:05:00

Running Graph API cmdlet with the Application Authentication.

Whether you use certificate authentication or client secret, once the script is connected, all is the same.

Let’s try Get-MgUser -all the results are

Id                                   DisplayName  Mail                                       UserPrincipalName                          UserType
--                                   -----------  ----                                       -----------------                          --------
6a5ec54c-5124-4116-ae6b-2a82ba061fec Faris Malaeb admin@powershellcenter2022.onmicrosoft.com admin@powershellcenter2022.onmicrosoft.com
3b02fdf3-ebc1-41ca-9d77-f36e4ff776f9 test1        test1@powershellcenter2022.onmicrosoft.com test1@powershellcenter2022.onmicrosoft.com

If the application tries to connect to other resources outside the granted permission, you get Insufficient privileges. For example, running Get-MgGroup -All return the following error

Get-MgGroup_List: Insufficient privileges to complete the operation.

This is normal as the application won’t have the required scope.

Conclusion

Microsoft provides several robust authentication methods. Add to that. The Graph API permission gives your script the exact permissions it needs to run the script/app successfully. I hope you found this post to be helpful.

5/5 - (6 votes)