-
-
Save JustinGrote/656a01c1e047df940d577698ba62e3f2 to your computer and use it in GitHub Desktop.
| #requires -version 7 -module Microsoft.Graph.Applications | |
| using namespace Microsoft.Graph.PowerShell.Models | |
| using namespace System.Collections.Generic | |
| enum MicrosoftGraphServicePrincipalType { | |
| Application | |
| Delegated | |
| } | |
| class MgServicePrincipalPermission { | |
| [MicrosoftGraphServicePrincipal]$ServicePrincipal | |
| [string]$Id | |
| [MicrosoftGraphServicePrincipalType]$Type | |
| [string]$User | |
| [string]$ResourceName | |
| [string]$Permission | |
| [string]$PermissionDisplayName | |
| [string]$Description | |
| [Nullable[DateTime]]$CreatedDateTime | |
| } | |
| Update-TypeData -TypeName 'MgServicePrincipalPermission' -DefaultDisplayPropertySet 'ServicePrincipal', 'ResourceName', 'User', 'Permission' -Force | Out-Null | |
| function Get-MgServicePrincipalPermission { | |
| <# | |
| .SYNOPSIS | |
| Retrieves the permissions assigned to a service principal, providing a similar output to what is on the Azure Portal Screen. | |
| .EXAMPLE | |
| Get-MgServicePrincipal -Search 'displayname:MyServicePrincipal' -Con eventual -Cou count | Get-MgServicePrincipalPermission | |
| #> | |
| [CmdletBinding(DefaultParameterSetName = 'Object')] | |
| param( | |
| [Parameter(ParameterSetName = 'Id', Position = 0, Mandatory, ValueFromPipelineByPropertyName)] | |
| [Alias('Id')] | |
| [string]$ServicePrincipalId, | |
| [Parameter(ParameterSetName = 'Object', Position = 0, Mandatory, ValueFromPipeline)] | |
| [Microsoft.Graph.PowerShell.Models.MicrosoftGraphServicePrincipal]$ServicePrincipal | |
| ) | |
| begin { | |
| #We use this to cache app info for permission lookups | |
| [Dictionary[string, MicrosoftGraphServicePrincipal]]$spCache = @{} | |
| } | |
| process { | |
| $ErrorActionPreference = 'Stop' | |
| $ServicePrincipal ??= Get-MgServicePrincipal -ServicePrincipalId $ServicePrincipalId | |
| #Add a ToString to the serviceprincipal so it summarizes correctly in the formatting | |
| $ServicePrincipal | Add-Member -MemberType ScriptMethod -Name ToString -Value { $this.DisplayName } -Force | |
| #When using Mandatory above, it becomes an empty string instead of null, so null conditional cannot be used. | |
| if ([string]::IsNullOrEmpty($ServicePrincipalId)) { | |
| $ServicePrincipalId = $ServicePrincipal.Id | |
| } | |
| $appPermissions = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $ServicePrincipalId | |
| | Where-Object DeletedDateTime -EQ $null | |
| foreach ($app in $appPermissions) { | |
| $spCache[$app.ResourceId] ??= Get-MgServicePrincipal -ServicePrincipalId $app.ResourceId | |
| [MicrosoftGraphAppRole]$role = $spCache[$app.ResourceId].AppRoles | |
| | Where-Object Id -EQ $app.AppRoleId | |
| if (-not $Role) { throw "No matching permission found for AppRoleID $($app.AppRoleId). This is a bug" } | |
| [MgServicePrincipalPermission]@{ | |
| ServicePrincipal = $ServicePrincipal | |
| Id = $app.Id | |
| Type = 'Application' | |
| User = '[Application]' | |
| ResourceName = $app.ResourceDisplayName | |
| Permission = $role.Value | |
| PermissionDisplayName = $role.DisplayName | |
| Description = $role.Description | |
| CreatedDateTime = $app.CreatedDateTime | |
| } | |
| } | |
| $delegatedPermissions = Get-MgServicePrincipalOauth2PermissionGrant -ServicePrincipalId $ServicePrincipalId | |
| foreach ($permission in $delegatedPermissions) { | |
| if (-not $spCache[$permission.ResourceId]) { | |
| $spCache[$permission.ResourceId] = Get-MgServicePrincipal -ServicePrincipalId $permission.ResourceId | |
| | Add-Member -MemberType ScriptMethod -Name ToString -Value { $this.DisplayName } -Force -PassThru | |
| } | |
| $resource = $spCache[$permission.ResourceId] | |
| foreach ($scope in $permission.Scope.split(' ')) { | |
| $role = $resource.AppRoles | Where-Object Value -EQ $scope | |
| [MgServicePrincipalPermission]@{ | |
| ServicePrincipal = $ServicePrincipal | |
| Id = $scope.Id | |
| Type = 'Delegated' | |
| User = $permission.ConsentType -eq 'AllPrincipals' ? 'All' : $permission.PrincipalId | |
| ResourceName = $resource.DisplayName | |
| Permission = $scope | |
| PermissionDisplayName = $role.DisplayName | |
| Description = $role.Description | |
| CreatedDateTime = $null | |
| } | |
| } | |
| } | |
| } | |
| } |
@rdantas9 works fine for me, not sure how you're invoking it that is causing the namespace errors.

@rdantas9 works fine for me, not sure how you're invoking it that is causing the namespace errors.
I was able to run your PowerShell script properly, but I've replaced line 12 from MicrosoftGraphServicePrincipal to Microsoft.Graph.PowerShell.Models.MicrosoftGraphServicePrincipal.
Thanks for your patience and support!
Hi, is 'Id = $app.Id' meant to be there in line 52 under $delegatedPermissions? If so, could you explain why?
Probably a cut/paste oopsie from the foreach loop above it, probably should be $scope.id
Thanks. Appreciate all your work.
Thanks @JustinGrote :)) Saved me reinventing the wheel here. Modified it a bit to list all the permissions in a gridview so I can select and delete Application permissions.

I'm running PowerShell 7.3.5. I'm trying to run Powershell script in another VM.