Table of Contents
Use PowerShell to Check for New Graph Permissions with a View to Updating Permissions Used by Apps
In my recent discussion about the appearance of new finer-grained Graph API permissions, I said that it’s a good idea for tenants to check for new permissions periodically. If you become aware of a new permission, you can assess whether it should replace a broader permission currently assigned to an application. For example, you might replace the User.ReadWrite.All permission for an app that updates user accounts but doesn’t need to create new accounts with the User.ReadUpdate.All permission.
I gave some examples of how to detect new Graph permissions, but most rely on someone noticing that a permission wasn’t available before. Obviously, only some of us can do such a thing. The challenge is obvious when you consider that there are 716 Graph application permissions and 807 OAuth delegated permissions to deal with at the time of writing. The number of permissions has grown over time as Microsoft introduces permissions for new workloads and finer-grained permissions for existing workloads.
Using Code to Automate Check for New Permissions
Computers are better than humans when it comes to performing boring, repetitive tasks. Comparing a set of permissions extracted some time ago with the current set of permissions to detect if any new permissions exist is exactly the kind of work we should automate.
Sketching the outline of a PowerShell script to do the work, the code might:
- Connect to the Microsoft Graph with the Connect-MgGraph cmdlet. The Application.Read.All permission is required to read all service principals in the tenant.
- Fetch the set of app roles (application permissions) and OAuth scopes (delegated permissions) from the Microsoft Graph service principal. The Graph service principal exists in every tenant, and we can fetch the app roles and OAuth scopes as follows:
$GraphSp = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'" [array]$AppRoles = $GraphSp.AppRoles | Select-Object Value, DisplayName, Id [array]$OAuthScopes = $GraphSp.OAuth2PermissionScopes | Select-Object Value, AdminConsentDisplayName, Id
- The script needs somewhere to hold the baseline data from the previous check. This could be a JSON file stored on a web site or anything else that seems good to you. I choose to use CSV files stored in a SharePoint Online document library. The next step is therefore to download the CSV files and load them into arrays that can be checked against the current data. Before using the script, you’ll need to update variables to tell the script which site, folder, and file names to use for the baseline data. You’ll also need to create the CSV files and upload them to the correct place.
- If the check reveals some new permissions, the code creates CSV files and uploads them to SharePoint Online to replace the files that it downloaded. These files become the basis for the next check.
- The script completes by creating and sending email to let interested parties know about what it found. Figure 1 shows the results of a run on August 29, 2026, after Microsoft added 13 new permissions to provide granular management of user authentication methods.

You can download the complete script from the Microsoft 365 for IT Pros GitHub repository.
The Azure Automation Option
I prefer to use Azure Automation scheduled runbooks for periodic checks like this, so I adapted the interactive version of the script to run in Azure Automation. Some code updates are always necessary, but I thought that minimal changes would be needed – literally, an update to use a system-assigned managed identity for authentication.
Alas, I was wrong. None of the cmdlets from the Microsoft.Graph.Files module (containing the cmdlets to interact with SharePoint and OneDrive files) worked in my customPowerShell V7.4 runtime environment. All the other Graph modules worked perfectly. I updated the environment several times with no joy. Any attempt to fetch or update a file with cmdlets like Get-MgDriveItemContent failed.
The headless nature of Azure Automation means that debugging can be challenging. I wrote a little code snippet to see what Azure Automation could see in terms of cmdlets in the module:
$FilesCmdlets = Get-Command -Module Microsoft.Graph.Files
If ($FilesCmdlets) {
Write-Output "Here's what I found for Files cmdlets"
$FilesCmdlets | Format-Table Name, Version
Write-Output ("{0} cmdlets found" -f $FilesCmdlets.count)
}
Azure Automation reported zilch. An interactive session reported 1252 cmdlets. A duff version of the module must be available to Azure Automation. The solution was to switch from Microsoft Graph PowerShell SDK cmdlets to Graph API requests, which worked (Figure 2).

As it happens, the bug is described in a closed bug for the Microsoft Graph PowerShell SDK. I’ve now reopened the issue as #3741. Given the number of cmdlets in the module, some form of resource limitation might be the root cause. The lesson here is that when a Graph SDK cmdlet doesn’t work for whatever reason, there’s always the underlying Graph API request to fall back on.
Checking is Only the Start
Knowing that something new is available is interesting, but it only becomes useful when the new knowledge is applied to gain some advantage. The same is true for new Graph permissions. New permissions don’t always justify action. Proposed changes should be tested carefully because replacing a broad permission with a narrower equivalent can expose hidden dependencies in application code. For example, User.ReadBasic.All seems like a good permission to use for apps that need access to user account information. It is, unless the app needs to filter on a property that isn’t revealed by the permission, like member type, or licenses.
It’s great to know that Microsoft has created new permissions, but the real challenge is making use of them. Discovering a new permission is easy. Finding every application that could benefit from the change is where the work begins.
Need help to write and manage PowerShell scripts for Microsoft 365, including Azure Automation runbooks? Get a copy of the Automating Microsoft 365 with PowerShell eBook, available standalone or as part of the Microsoft 365 for IT Pros eBook bundle.