Invoke-GraphAPIRequest.ps1

 <#
.AUTHOR
    Nik Chikersal
.SYNOPSIS
    This function is used to make Graph REST API Requests to Microsoft Graph with automatic bearer token retrieval
.EXAMPLE
    Invoke-GraphAPIRequest -GraphResource 'groups' -UseMSI
    This example shows how to retrieve a list of resources (Example: Groups) using MSI
     
    Invoke-GraphAPIRequest -GraphResource 'groups'
    This example shows how to retrieve a list of resources (Example: Groups) without using MSI
.NOTES
Validate set within function is being worked on to include entity sets, rather than just the ones listed below.
#>

function Invoke-GraphAPIRequest {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)][ValidateNotNullOrEmpty()]
        #Needswork to include entity sets [ValidateSet("directoryObjects", "invitations", "users", "activitystatistics", "applicationTemplates", "servicePrincipals", "authenticationMethodConfigurations", "bookingBusinesses", "bookingCurrencies", "devices", "identityProviders", "deviceLocalCredentials", "administrativeUnits", "allowedDataLocations", "applications", "appRoleAssignments", "certificateBasedAuthConfiguration", "contacts", "contracts", "directoryRoles", "directoryRoleTemplates", "directorySettingTemplates", "domainDnsRecords", "domains", "groups", "oauth2PermissionGrants", "organization", "permissionGrants", "scopedRoleMemberships", "settings", "subscribedSkus", "places", "drives", "shares", "sites", "messageEvents", "messageRecipients", "messageTraces", "schemaExtensions", "onPremisesPublishingProfiles", "groupLifecyclePolicies", "filterOperators", "functions", "accessReviewDecisions", "accessReviews", "approvalWorkflowProviders", "businessFlowTemplates", "programControls", "programControlTypes", "programs", "agreementAcceptances", "agreements", "riskDetections", "riskyUsers", "mobilityManagementPolicies", "governanceResources", "governanceRoleAssignmentRequests", "governanceRoleAssignments", "governanceRoleDefinitions", "governanceRoleSettings", "governanceSubjects", "privilegedAccess", "privilegedApproval", "privilegedOperationEvents", "privilegedRoleAssignmentRequests", "privilegedRoleAssignments", "privilegedRoles", "privilegedSignupStatus", "commands", "payloadResponse", "dataPolicyOperations", "subscriptions", "connections", "chats", "teams", "teamsTemplates", "teamTemplateDefinition", "identityGovernance", "auditLogs", "reports", "solutions", "authenticationMethodsPolicy", "identity", "deviceManagement", "roleManagement", "privacy", "security", "compliance", "trustFramework", "dataClassification", "informationProtection", "monitoring", "conditionalAccess", "directory", "me", "policies", "tenantRelationships", "admin", "education", "drive", "employeeExperience", "termStore", "communications", "identityProtection", "deviceAppManagement", "search", "financials", "planner", "print", "threatSubmission", "app", "external", "appCatalogs", "teamwork", "networkAccess")]
        [String]$GraphResource,
        [Parameter(Mandatory = $false)][ValidateNotNullOrEmpty()]
        [switch]$UseMSI  
    )

    if ([string]::IsNullOrEmpty($global:BearerToken)) {
       if ($UseMSI) {
         try {
            $global:BearerToken = Get-GraphAccessToken -UseMSI
         }
         catch {
            Write-Warning $Global:Error.Exception.Message[0]
        } 
    }
    elseif (!$UseMSI) {
         try {
            $global:BearerToken = Get-GraphAccessToken
         }
         catch {
            Write-Warning $Global:Error.Exception.Message[0]
          }
       }
    }
    $global:Results = [System.Collections.ArrayList]::new()
    [hashtable]$SplatArgs = @{
        Headers = @{Authorization = "Bearer $($global:BearerToken)"}
        Uri     = "https://graph.microsoft.com/Beta/$($GraphResource)" 
        Method  = 'GET'
   }
    try {
         do {
            $GraphResponse = Invoke-RestMethod @SplatArgs 
            foreach ($Response in $GraphResponse.Value) {
                [void]$Results.Add($Response)
            }
            $SplatArgs.Uri = $GraphResponse."@odata.nextLink"
        } while ($SplatArgs.Uri)
           if (![string]::IsNullOrEmpty($Results)) {
            return $global:results
        }        
    }
    catch {
        [PSCustomObject]@{
            CommandException = $($Global:Error.Exception)[0]
        }
         if ($IsWindows) { 
          Start-Sleep -Seconds 3 ; [System.Diagnostics.Process]::Start("C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe","https://learn.microsoft.com/en-us/graph/permissions-reference")
          [PSCustomObject][Ordered]@{
            Error = $($Global:Error.Exception.Message)[0]
            Msg   = "Please Visit: https://learn.microsoft.com/en-us/graph/permissions-reference"
        }
    }
    elseif ($IsMacOS -or $UseMSI) {
        [PSCustomObject][Ordered]@{
            Error = $($Global:Error.Exception.Message)[0]
            Msg   = "Please Visit: https://learn.microsoft.com/en-us/graph/permissions-reference"
        } 
    }
}

if (!$UseMSI) {
[string]$PermissionsConsent = Read-Host "Would you like to consent to Graph Permissions? Type 'Y' to consent or 'N' to exit"
  Switch ($PermissionsConsent) {
      'Y' { $SetPermissions = Read-Host "Enter the permissions you would like to consent to. Example: 'User.Read, Group.ReadWrite.All'"
          if (![string]::IsNullOrEmpty($SetPermissions)) {
            Try {
                $ConsentCheck = Connect-MgGraph -Scopes $SetPermissions -ErrorAction STOP
                if (($ConsentCheck | Select-String -Pattern "Welcome to Microsoft Graph!")) {
                    Write-Host "Permissions have been consented successfully: $($SetPermissions)" -ForegroundColor Green
                }
            }
           catch {
                If (($Global:Error[0] | Select-String -Pattern "User declined to consent to access the app")) {
                Write-Warning "Permissions were not consented because the prompt was canceled or consent isn't allowed"
             }
             elseif (($Global:Error[0] | Select-String -Pattern "that doesn't exist on the resource" )) {
                Write-Warning "Permissions were not consented because the permissions you entered are not valid"
                Start-Sleep -Seconds 10; Exit 1
               }
               elseIf (($Global:Error[0] | Select-String -Pattern "that doesn't exist on the resource") -or ($Global:Error[0] | 
                 Select-String -Pattern "User declined to consent to access the app" -NotMatch)) {
                 Write-Warning "$($SetPermissions): is not a valid permission. Please visit: https://docs.microsoft.com/en-us/graph/permissions-reference"
                 Start-Sleep -Seconds 10; Exit 1
               }
            }
        }
    }
    'N' { Write-Warning "Exiting..."}
    default {Write-Warning "Exiting..."}}
    $Global:Error.Clear() 
   }
}