Contents
Introduction
Microsoft Graph API is a powerful tool for automating and managing resources within the Microsoft 365 ecosystem. However, running unattended automation scripts with Microsoft Graph presents security and authentication challenges. Traditionally, service principals (app registrations) and client secrets or certificates are used to authenticate API requests. However, these methods introduce security risks, such as secret leakage, and require lifecycle management.
A more secure and efficient alternative is Azure Arc-enabled managed identity for on-premises servers, which allows seamless authentication without managing service principal credentials.
With Azure Arc, you can onboard on-premises or non-Azure servers to Azure Resource Manager (ARM). This allows the server to leverage managed identities, providing a seamless and secure authentication mechanism to access Microsoft Graph API.
How Azure Arc-Enabled Managed Identity Solves These Challenges
✅ Eliminates Secrets and Certificates – No need to store and rotate secrets.
✅ Native Integration with Microsoft Entra ID (formerly Azure AD) – Enables secure API authentication.
✅ Applies Least Privilege Principle – You can assign only necessary permissions.
✅ Securely Extends Azure Capabilities to On-Premises – Brings Azure-native security to on-prem resources.
Onboard Your On-Premises Server to Azure Arc
Azure Arc Setup is included by default on new Windows Server 2022 installations and later.
It typically sits under %windir%\AzureArcSetup\ArcSetup\AzureArcSetup.exe
For more information click to learn more on how to Connect Windows Server machines to Azure through Azure Arc Setup
Grant Graph API Permissions to Arc-enabled on-prem Server Managed Identity
Once the machine has connected to Azure, head to your Azure Portal (Portal.azure.com) and search for Azure Arc, then Machines

This will allow you to assign API permissions to the server similar to any Azure App Registration or Service Principal with a Managed System Identity.
Searching the server name in Enterprise Applications (filtering by Managed Identity), you should be able to find it listed

Clicking on the server name, and going to Permissions, there is no way to grant API permissions directly through the console. For that we will need to use Powershell!

To grant permissions to your Server Managed Identity, open up Powershell on your PC, and run the following code.
You will need to replace the variable values for $tenantID and $ManagedIdenityID. Check the inline comments in the code for more details.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# Script to assign Graph API permissions to an existing managed identity # The following Microsoft Graph permissions will be assigned: # DeviceManagementManagedDevices.Read.All # User.Read.All # GroupMember.Read.All # Application.Read.All # Prerequisites: Import-Module Microsoft.Graph.Authentication Import-Module Microsoft.Graph.Applications # Variables $tenantId = "<Replace_with_tenant_id>" # Your tenant ID $managedIdentityID = "<Replace_with_Managed_Identity_Object_id>" #the object id of the managed identity to which permissions needs adding # Log in as a user with the "Privileged Role Administrator" role Connect-MgGraph -TenantId $tenantId -Scopes "AppRoleAssignment.ReadWrite.All,Application.Read.All" # Search for Microsoft Graph built-in service principal $MSGraphServicePrincipal = Get-MgServicePrincipal -Filter "DisplayName eq 'Microsoft Graph'"; # Search for the managed identity of the Arc Enabled Server $ManagedSystemIdentity = Get-MgServicePrincipal -ServicePrincipalId "$managedIdentityID" #write-host $ManagedSystemIdentity write-host $MSGraphServicePrincipal # Get required permissions in an array. Change the permissions as needed $Permissions = @( "User.Read.All" "GroupMember.Read.All" "Application.Read.All" "DeviceManagementManagedDevices.Read.All" ) # Find app permissions from the above array within Microsoft Graph application $MSGraphAppRoles = $MSGraphServicePrincipal.AppRoles | Where-Object {($_.Value -in $Permissions)} # Assign the managed identity app roles for each permission foreach($AppRole in $MSGraphAppRoles) { $AppRoleAssignment = @{ principalId = $ManagedSystemIdentity.Id # Managed Identity Object ID resourceId = $MSGraphServicePrincipal.Id # Microsoft Graph Service Principal ID appRoleId = $AppRole.Id # App Role ID } # Assign the app role to the managed identity New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $AppRoleAssignment.PrincipalId -BodyParameter $AppRoleAssignment -Verbose } |
The output should look like this

Go back to the Azure portal and refresh the page on which the permissions are granted, and it should show that the server managed identity has been successfully granted permissions to call Microsoft Graph for the permissions specified

Head to your Arc-enabled server and login as Administrator and fire up PowerShell ISE (or VSCode)
Ensure you have installed the relevant module from Microsoft.Graph for your needs. In this example, I am going to query Intune Managed devices in my tenant so will be installing Microsoft.Graph.DeviceManagement
|
1 2 3 4 5 6 7 8 9 |
# Install required modules silently if not already installed if (-not (Get-Module -ListAvailable -Name Microsoft.Graph)) { Install-Module -Name Microsoft.Graph.DeviceManagement -AllowClobber -Scope CurrentUser -Force -Confirm:$false } # Import the module Import-Module -Name Microsoft.Graph.DeviceManagement -ErrorAction Stop -verbose |
Now, we will connect to MgGraph without using any credentials! we will simply use the identity of the server to connect.
|
1 2 3 4 5 6 7 |
# Authenticate to Microsoft Graph using managed identity Connect-MgGraph -Identity #Get the context of the user connected to MgGraph Get-MgContext |
The output should look as follows. Notice that the scopes shows the access token has the correct permissions for your automation needs and the AuthType and TokenCredentialType are ManagedIdentity.

Let’s query Intune managed devices and get the lastsyncdatetime and OS name for them
|
1 2 3 4 |
# Get devices managed by Intune Get-MgDeviceManagementManagedDevice | select DeviceName, Operatingsystem, LastSyncDateTime |

Conclusion
Using Azure Arc-enabled managed identity for running unattended Microsoft Graph automation on an on-premises server removes the need for credentials, enhances security, and simplifies authentication. It ensures a zero-trust approach while maintaining compliance and efficiency.
By leveraging Azure Arc, organizations can extend cloud-native security and identity management to their on-premises infrastructure, making automation with Microsoft Graph both seamless and secure.