How to read Microsoft Graph API delegated and application permissions programmatically

Microsoft Graph is the gateway to data and intelligence in Microsoft 365. Microsoft Graph supports delegated and app-only access. Microsoft Graph exposes delegated and application permissions.

With delegated permissions, the app can access data on behalf of a signed-in user. Other names for delegated permissions are scopes and OAuth2 permissions.

Application permissions allow the app to access data with its own identity, without a signed-in user. Application permissions can be called app roles, app-only permissions, or direct access permissions.

Documentation contains details of both delegated and application permissions.

But what if you want to access those permissions programatically for further usage in your app or to export them?

Fortunately, the Graph API itself allows to get details of delegated and applications permissions.

Service principal

The servicePrincipal resource represents an instance of an application in Azure Active Directory. servicePrincipal has properties:

  • appId - the unique identifier for the associated application
  • appRoles - the collection of the application roles exposed by the application
  • oauth2PermissionScopes - the collection of the delegated permissions exposed by the application

The appRole can be assigned to users and groups or to other application. The appRole assigned to another application is also known as application permission.

Read permissions

In Azure Active Directory, create a new app with the application permission Application.Read.All which allows to read all servicePrincipal objects and their properties.

img

Create a new secret for the app:

img

I will use the Microsoft Graph PowerShell SDK to read and export permissions.

Install the latest release candidate of the Microsoft Graph module:

Install-Module -Name Microsoft.Graph -RequiredVersion "2.0.0-rc1" -AllowPrerelease

The latest release candidate allows you to connect to the Graph API with a client secret.

Use client id, tenant id, and secret:

img

Connect to the app in Azure AD:

$clientId = "<client_id>"
$tenantId = "<tenant_id>"
$secret = "<secret>"

$securedSecret = ConvertTo-SecureString -String $secret -AsPlainText -Force

$clientSecretCredential = New-Object `
-TypeName System.Management.Automation.PSCredential `
-ArgumentList $clientId, $securedSecret

Connect-MgGraph -TenantId $tenantId -ClientSecretCredential $clientSecretCredential

Read delegated and application permissions for the Microsoft Graph application:

Import-Module Microsoft.Graph.Applications

$data = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'" -Property "displayName,appRoles,oauth2PermissionScopes"

The Microsoft Graph application has the same app id 00000003-0000-0000-c000-000000000000 across all tenants, but if you want to be sure, you can either check the app id in Azure Active Directory or filter the app by name:

$data = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Property "displayName,appRoles,oauth2PermissionScopes"

Export permissions to csv:

$data.AppRoles | Where-Object { $_.AllowedMemberTypes -contains 'Application' } | Select-Object Value, Id, DisplayName, Description, Origin, IsEnabled | Export-Csv -Path $appPermissionsOutputFile -NoTypeInformation
$data.Oauth2PermissionScopes | Select-Object Value, Id, UserConsentDisplayName, UserConsentDescription, AdminConsentDescription, AdminConsentDisplayName, Type, IsEnabled | Export-Csv -Path $delegatedPermissionsOutputFile -NoTypeInformation

The whole script can be found in GitHub repository.

$appPermissionsOutputFile = ".\Graph_ApplicationPermissions.csv"
$delegatedPermissionsOutputFile = ".\Graph_DelegatedPermissions.csv"

$clientId = "<client_id>"
$tenantId = "<tenant_id>"
$secret = "<secret_value>"

$securedSecret = ConvertTo-SecureString `
-String $secret -AsPlainText -Force

$clientSecretCredential = New-Object `
-TypeName System.Management.Automation.PSCredential `
-ArgumentList $clientId, $securedSecret

Connect-MgGraph -TenantId $tenantId -ClientSecretCredential $clientSecretCredential

Import-Module Microsoft.Graph.Applications

$data = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'" -Property "displayName,appRoles,oauth2PermissionScopes"

$data.AppRoles | Where-Object { $_.AllowedMemberTypes -contains 'Application' } | Select-Object Value, Id, DisplayName, Description, Origin, IsEnabled | Export-Csv -Path $appPermissionsOutputFile -NoTypeInformation

$data.Oauth2PermissionScopes | Select-Object Value, Id, UserConsentDisplayName, UserConsentDescription, AdminConsentDescription, AdminConsentDisplayName, Type, IsEnabled | Export-Csv -Path $delegatedPermissionsOutputFile -NoTypeInformation

If you want to list permissions for other common applications, there is a list of their names with app id:

Name App id
Azure ESTS Service 00000001-0000-0000-c000-000000000000
Windows Azure Active Directory 00000002-0000-0000-c000-000000000000
Office 365 Exchange Online 00000002-0000-0ff1-ce00-000000000000
Microsoft Graph 00000003-0000-0000-c000-000000000000
Office 365 SharePoint Online 00000003-0000-0ff1-ce00-000000000000
Skype for Business Online 00000004-0000-0ff1-ce00-000000000000
Microsoft Azure Workflow 00000005-0000-0000-c000-000000000000
Yammer 00000005-0000-0ff1-ce00-000000000000
Microsoft Office 365 Portal 00000006-0000-0ff1-ce00-000000000000
Dataverse 00000007-0000-0000-c000-000000000000
Microsoft Exchange Online Protection 00000007-0000-0ff1-ce00-000000000000
Microsoft.Azure.DataMarket 00000008-0000-0000-c000-000000000000
Power BI Service 00000009-0000-0000-c000-000000000000
Microsoft Intune 0000000a-0000-0000-c000-000000000000
Microsoft Seller Dashboard 0000000b-0000-0000-c000-000000000000
Microsoft App Access Panel 0000000c-0000-0000-c000-000000000000
Microsoft Rights Management Services 00000012-0000-0000-c000-000000000000
Microsoft Power BI Information Service 0000001b-0000-0000-c000-000000000000
0
Buy Me a Coffee at ko-fi.com
An error has occurred. This application may no longer respond until reloaded. Reload x