Private/Resolve-TLAppId.ps1

function Resolve-TLAppId {
    <#
    .SYNOPSIS
        Resolves application (client) ids to service principal display names.
    .DESCRIPTION
        Conditional Access references applications by appId, not object id, so
        getByIds cannot be used. Uses $filter=appId in (...) in chunks of 15.
        Well-known tokens ('All', 'Office365', 'MicrosoftAdminPortals', 'None')
        pass through unchanged.
    #>

    [CmdletBinding()]
    param(
        [AllowEmptyCollection()]
        [AllowNull()]
        [string[]]$AppId
    )

    $result = @{}
    if (-not $AppId -or @($AppId).Count -eq 0) { return $result }

    $guidPattern = '^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$'
    $toLookup = [System.Collections.Generic.List[string]]::new()

    foreach ($value in @($AppId | Where-Object { $_ } | Sort-Object -Unique)) {
        if ($value -notmatch $guidPattern) { $result[$value] = $value; continue }
        if ($script:TLAppIdCache.ContainsKey($value)) { $result[$value] = $script:TLAppIdCache[$value]; continue }
        $toLookup.Add($value)
    }

    for ($offset = 0; $offset -lt $toLookup.Count; $offset += 15) {
        $chunk = @($toLookup[$offset..([Math]::Min($offset + 14, $toLookup.Count - 1))])
        $filterExpression = "appId in ({0})" -f (($chunk | ForEach-Object { "'{0}'" -f $_ }) -join ',')
        $uri = '/v1.0/servicePrincipals?$filter=' + [uri]::EscapeDataString($filterExpression) + '&$select=appId,displayName'
        $found = @()
        try {
            $found = @(Invoke-TLGraphRequest -Uri $uri -All)
        }
        catch {
            Write-Verbose ("Service principal lookup failed for {0} appIds: {1}" -f $chunk.Count, $_.Exception.Message)
        }
        foreach ($servicePrincipal in $found) {
            $script:TLAppIdCache[$servicePrincipal.appId] = [string]$servicePrincipal.displayName
            $result[$servicePrincipal.appId] = [string]$servicePrincipal.displayName
        }
        foreach ($miss in $chunk) {
            if (-not $result.ContainsKey($miss)) {
                $script:TLAppIdCache[$miss] = $miss
                $result[$miss] = $miss
            }
        }
    }

    return $result
}