Private/Test-MgGraphPermission.ps1
|
<#
.SYNOPSIS Verifies that the current Microsoft Graph token has the required scopes. .DESCRIPTION Reads the scopes from Get-MgContext and checks that every requirement listed in -RequiredScopes is present. A stronger scope satisfies a weaker requirement following the hierarchy ReadBasic < Read < ReadWrite (e.g. Application.ReadWrite.All covers Application.Read.All, and BitlockerKey.Read.All covers BitlockerKey.ReadBasic.All). A requirement may list alternatives separated by '|' (e.g. 'Policy.Read.All|Policy.ReadWrite.MobilityManagement'): the requirement is satisfied when any one of the alternatives is granted, mirroring the permission lists of the Microsoft Graph documentation. Returns $true when every requirement is satisfied, otherwise writes a warning listing the missing scopes and returns $false. .PARAMETER RequiredScopes One or more Microsoft Graph scope requirements that the calling function needs. Each entry is either a single scope or several alternatives separated by '|'. .PARAMETER CallerName (Optional) Name of the caller, used to make the warning message clearer. #> function Test-MgGraphPermission { [CmdletBinding()] [OutputType([bool])] param ( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string[]]$RequiredScopes, [Parameter(Mandatory = $false)] [string]$CallerName = (Get-PSCallStack)[1].Command ) # Scopes suggested in warning messages: the first alternative of each requirement $suggestedScopes = foreach ($requirement in $RequiredScopes) { ($requirement -split '\|')[0].Trim() } $context = Get-MgContext -ErrorAction SilentlyContinue if (-not $context) { Write-Warning "[$CallerName] No active Microsoft Graph session. Run Connect-MgGraph -Scopes $($suggestedScopes -join ',')" return $false } $grantedScopes = @($context.Scopes) $missingScopes = foreach ($requirement in $RequiredScopes) { [System.Collections.Generic.List[string]]$acceptedScopes = @() foreach ($alternative in ($requirement -split '\|')) { $alternative = $alternative.Trim() $acceptedScopes.Add($alternative) # A stronger scope satisfies a weaker requirement: ReadBasic < Read < ReadWrite if ($alternative -match '\.ReadBasic\.') { $acceptedScopes.Add(($alternative -replace '\.ReadBasic\.', '.Read.')) $acceptedScopes.Add(($alternative -replace '\.ReadBasic\.', '.ReadWrite.')) } elseif ($alternative -match '\.Read\.') { $acceptedScopes.Add(($alternative -replace '\.Read\.', '.ReadWrite.')) } } $satisfied = $false foreach ($acceptedScope in $acceptedScopes) { if ($acceptedScope -in $grantedScopes) { $satisfied = $true break } } if (-not $satisfied) { $requirement -replace '\|', ' or ' } } if ($missingScopes) { Write-Warning "[$CallerName] The current Microsoft Graph token is missing the following scope(s): $($missingScopes -join ', ').`n`nReconnect with:`nConnect-MgGraph -NoWelcome -Scopes $($suggestedScopes -join ',')" return $false } return $true } |