checks/library/third-party-consent-grants.ps1

# Tenant-wide delegated consent grants whose RESOURCE is a non-Microsoft (third-party) API.
$items = @()
$cache = @{}
function ResolveSp($id) {
    if ($cache.ContainsKey($id)) { return $cache[$id] }
    $sp = try { Invoke-MgGraphRequest -Method GET -OutputType PSObject -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$id`?`$select=displayName,appOwnerOrganizationId,appId" } catch { $null }
    $cache[$id] = $sp
    $sp
}
foreach ($g in Get-GraphAll "https://graph.microsoft.com/v1.0/oauth2PermissionGrants?`$top=999") {
    if ($g.consentType -ne 'AllPrincipals') { continue }
    $res = ResolveSp $g.resourceId
    if (-not $res) { continue }
    if (Test-MicrosoftFirstParty $res) { continue }   # skip Microsoft resources (Graph, etc.)
    $client = ResolveSp $g.clientId
    $clientName = if ($client -and $client.displayName) { $client.displayName } else { $g.clientId }
    $items += [pscustomobject]@{
        Title  = "$clientName -> $($res.displayName)"
        Detail = "Tenant-wide delegated grant to a third-party API; scopes: $($g.scope)"
    }
}
[pscustomobject]@{
    Name     = 'OAuth2 grants to third-party (non-Microsoft) APIs'
    Severity = 'medium'
    Fix      = 'Review third-party API consents; revoke unused grants and prefer per-user consent.'
    Items    = $items
}