functions/Invoke-AadProtectedApi.ps1
<#
.SYNOPSIS Make a API request to a protected AAD resource using a Accesss Token. .DESCRIPTION Make a API request to a protected AAD resource using a Accesss Token. .PARAMETER Endpoint This is the API url you are making a request to. .PARAMETER AccessToken Pass the access token to the protected API .PARAMETER GET Make a GET request to the protected API .PARAMETER PATCH Use the PATCH Http Method .PARAMETER POST Use the POST Http Method .PARAMETER DELETE Use the DELETE Http Method .PARAMETER PUT Use the PUT Http Method .PARAMETER Body Include a body content with your API request .PARAMETER ContentType Specify a ContentType to use. (Default application/json) .EXAMPLE Invoke-AadProtectedApi -GET -Endpoint "https://graph.microsoft.com/v1.0/me" -AccessToken "eyJ***" .NOTES General notes #> function Invoke-AadProtectedApi { [CmdletBinding(DefaultParameterSetName="All")] Param( [Parameter(Mandatory=$true)] [string]$Endpoint, [Parameter(ParameterSetName="ProvideToken_Get", Mandatory=$True)] [string]$AccessToken, [Parameter(ParameterSetName="GetToken_Get", Mandatory=$True)] [string]$Client, [Parameter(ParameterSetName="GetToken_Get", Mandatory=$True)] [string]$Resource, [ValidateSet('GET','PATCH','POST','PUT','DELETE')] $Method = "GET", [string] $Body, $ContentType = "application/json" ) #end param # Parameter requirements if ( ($Method -eq "POST" -or $Method -eq "PATCH" -or $Method -eq "PUT") -and -not $Body ) { throw "Body required when using POST, PATCH, or PUT" } if(-not $AccessToken -and -not $Client) { throw "You must specify either -AccessToken or -Client" } # Check if Body is file if($Body) { if(Test-Path -Path $Body) { $content = Get-Content -Path $Body -Raw $Body = $content } } if($Client -and $Resource) { if($Client -eq $Global:AadSupport.Clients.AzureAdPowerShell.ClientId -or $Client -eq $Global:AadSupport.Clients.AzurePowerShell.ClientId ) { $ClientId = $Client } else { $ClientId = (Get-AadServicePrincipal -Id $Client).AppId } $ResourceId = (Get-AadServicePrincipal -Id $Resource).AppId if(!$ClientId) { $ClientId = $Client } if(!$ResourceId) { $ResourceId = $Client } write-verbose "Getting token for $Client and $Resource" $token = Get-AadTokenUsingAdal -ClientId $ClientId -ResourceId $ResourceId -UserId $Global:AadSupport.Session.AccountId -Prompt Auto -HideOutput -SkipServicePrincipalSearch if($token["Error"]) { return $token["Error"] } $AccessToken = $token.AccessToken } $Result = @{} $Result.Content = @() $nextLink = $null $RetryAttempts = 0 $MaxRetryAttempts = 5 do { Show-AadSupportStatusBar # Refresh Token if ClientId and ResourceId provided if($ClientId -and $ResourceId) { $token = Get-AadTokenUsingAdal -ClientId $ClientId -ResourceId $ResourceId -UserId $Global:AadSupport.Session.AccountId -Prompt Auto -HideOutput -SkipServicePrincipalSearch $AccessToken = $token.AccessToken } #Start-Sleep -Milliseconds 60 if($nextLink) { $endpoint = $nextLink $nextLink = $null } try { write-verbose "Making Graph call..." if ($Method -eq "GET") { $request = Invoke-WebRequest -Headers @{ "Authorization" = "Bearer $AccessToken" } -Uri $endpoint -Method GET -ContentType $ContentType } if ($Method -eq "POST" -or $Method -eq "PATCH" -or $Method -eq "PUT") { $request = Invoke-WebRequest -Headers @{ "Authorization" = "Bearer $AccessToken" } -Uri $endpoint -Method $Method -Body $Body -ContentType $ContentType } if ($Method -eq "DELETE") { $request = Invoke-WebRequest -Headers @{ "Authorization" = "Bearer $AccessToken" } -Uri $endpoint -Method $Method -ContentType $ContentType } } catch{ $RetryAttempts++ Start-Sleep -Milliseconds (1000*$RetryAttempts*2) Write-Host "Exception calling API." -ForegroundColor Red if($request.Response.Content) { $String = $request.Response.Content } elseif($_.Exception.Response) { $reqstream = $_.Exception.Response.GetResponseStream() $reqstream.Position = 0 $stream = [System.IO.StreamReader]::new($reqstream) $String = $stream.ReadToEnd() $stream.Close() $reqstream.Close() } Write-Host $String -ForegroundColor Yellow if($_.Exception.Response.StatusCode -eq "429") { Write-Host "Throttling limit hit: StatusCode 429: Waiting 1 minute. It may take up to 5 minutes" -ForegroundColor Yellow Start-Sleep -Seconds 61 Continue } elseif($_.Exception.Response.StatusCode -eq "Unauthorized") { Write-Host "Invalid Access Token." -ForegroundColor Yellow throw $_ } elseif($_.Exception.Response.StatusCode -eq "Forbidden") { Write-Host "Missing Permissions." -ForegroundColor Yellow Start-Sleep -Seconds 300 throw $_ } if($RetryAttempts -gt $MaxRetryAttempts) { throw $_ } Write-Host "" Write-Host "Retrying request!" -ForegroundColor Yellow continue } try{ $JsonObject = $request.Content | ConvertFrom-Json if($JsonObject.Value) { $Result.Content += $JsonObject.Value if($JsonObject.'@odata.nextLink') { $nextLink = $JsonObject.'@odata.nextLink' } if($JsonObject.'odata.nextLink') { if(-not $nextLink -match "https") { $nextLink = $JsonObject.'odata.nextLink' Write-Host "nextLink is not a valid web address." Write-Host $nextLink } } } else{ $Result.Content += $JsonObject } } catch{ $Result.Content += $request.Content } } while ($nextLink) $Result.Headers = $request.Headers $Result.StatusCode = $request.StatusCode $Result.Response = $request if($Result) { Write-Verbose $request.Headers Write-Verbose $request.StatusCode Write-Verbose $Result.Response } $ReturnObject = New-Object -TypeName PsCustomObject -Property $Result if($ReturnObject.Content) { $members = $ReturnObject.Content | Get-Member | where {$_.MemberType -eq "NoteProperty"} $ValuePropertyExist = $members.Name.Contains("value") } if(!$ReturnObject.Content.Value -and $ValuePropertyExist) { return $null } return $ReturnObject.Content } function Test-InvokeAadProtectedApi { Remove-Module AadSupportPreview Import-Module AadSupportPreview Connect-AadSupport # Test 1 returned result from a collection $endpoint = "$($Global:AadSupport.Resources.MsGraph)/beta/users?`$filter=userPrincipalName eq 'admin@williamfiddes.onmicrosoft.com'" $result = Invoke-AadProtectedApi -Client 'test native app' -Resource 'Microsoft Graph' -Endpoint $Endpoint # Test 0 returned results from a collection $endpoint = "$($Global:AadSupport.Resources.MsGraph)/beta/users?`$filter=userPrincipalName eq 'admin@williamfiddes.onmicrosot.com'" $result = Invoke-AadProtectedApi -Client 'test native app' -Resource 'Microsoft Graph' -Endpoint $Endpoint # Test 1 returned result $endpoint = "$($Global:AadSupport.Resources.MsGraph)/beta/users/admin@williamfiddes.onmicrosoft.com" $result = Invoke-AadProtectedApi -Client 'test native app' -Resource 'Microsoft Graph' -Endpoint $Endpoint # Test Pagination $endpoint = "$($Global:AadSupport.Resources.MsGraph)/beta/users?`$top=10" $result = Invoke-AadProtectedApi -Client 'test native app' -Resource 'Microsoft Graph' -Endpoint $Endpoint } |