Powershell Invoke-RestMethod Paging - powershell

I am trying to get a list of all users from our Azure B2C tenant.
With some help from the internet I was able to create the powershell script below. But the result is incomplete it only shows 100 users. After searching around I found I should probably do something with Paging but I can't get it to work.
Can someone help me to modify the script below to return all users?
# Application (client) ID, tenant Name and secret
$clientId = "**********"
$tenantName = "*********"
$clientSecret = "************"
$resource = "https://graph.microsoft.com/"
$ReqTokenBody = #{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
client_Id = $clientID
Client_Secret = $clientSecret
}
$TokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token" -Method POST -Body $ReqTokenBody
$Url = "https://graph.microsoft.com/beta/users?$select=displayName"
$Data = Invoke-RestMethod -Headers #{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $Url -Method Get
$Users = ($Data |select-object Value).Value
$Users | Format-Table DisplayName -AutoSize

Ok i got it to work in Powershell Core (Version 7.1.3).
This is the code I ended up using.
# Application (client) ID, tenant Name and secret
$clientId = "**************"
$tenantName = "***************"
$clientSecret = "******************"
$resource = "https://graph.microsoft.com/"
$ReqTokenBody = #{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
client_Id = $clientID
Client_Secret = $clientSecret
}
$TokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token" -Method POST -Body $ReqTokenBody
$Url = "https://graph.microsoft.com/beta/users?$select=displayName"
$UserResponse = Invoke-RestMethod -Headers #{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $Url -Method Get -Verbose
$CloudUser = $UserResponse.Value
$UserNextLink = $UserResponse."#odata.nextLink"
while ($UserNextLink -ne $null) {
$UserResponse = (Invoke-RestMethod -Headers #{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $UserNextLink -Method Get -Verbose)
$UserNextLink = $UserResponse."#odata.nextLink"
$CloudUser += $UserResponse.value
}
$CloudUser | Format-Table DisplayName -AutoSize

Most of the last 8 lines (or so) are repeated. You can factor it out like this:
$Url = "https://graph.microsoft.com/beta/users?$select=displayName"
$headers = #{Authorization = "Bearer $($Tokenresponse.access_token)"}
$CloudUser = #()
do {
$UserResponse = Invoke-RestMethod -Headers $headers -Uri $Url -Method Get -Verbose
$CloudUser += $UserResponse.Value
$Url = $UserResponse."#odata.nextLink"
} while ($Url)
Also, why not use the Graph PowerShell module for this? https://learn.microsoft.com/en-us/powershell/microsoftgraph

Related

Post Chat message using Graphapi via Powershell using Delegate Grant type

Post Chat message using Graphapi via Powershell using Delegate Grant type using password grant
#Group chat Message
$granttype = 'password'
$tenantID = '695bbc7172e0'
$scope = 'https://graph.microsoft.com/.default'
$clientSecret = (ConvertTo-SecureString "O4UN4ndB" -AsPlainText -Force )
$cred = Import-Clixml C:\temp\credentials.xml
$redirectUri = "https://testexchangeewsdelegate.com"
# Construct URI
$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
# Construct Body
$body = #{
clientId = "0e003e593d"
scope = $scope
grant_type = $granttype
username = $cred.UserName
password = $cred.GetNetworkCredential().password
}
$TokenResponses = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token" -Method POST -Body $ReqTokenBody
$apiUrl = 'https://graph.microsoft.com/v1.0/chats/19:987345050c22c8369df1a6#thread.v2'
Invoke-RestMethod -Headers #{Authorization = "Bearer $($Tokenresponses.access_token)"} -Uri $apiUrl -Method Get -ContentType "application/x-www-form-urlencoded"
$apiUrl1 = 'https://graph.microsoft.com/v1.0/chats/19:987345050c22c8369df1a6#thread.v2/messages'
$params = #{
Body = #{ Content = "Hello World"} }
$bodyJSON = $params| ConvertTo-Json
Invoke-RestMethod -Headers #{Authorization = "Bearer $($Tokenresponses.access_token)"} -Uri $apiUrl1 -Method Post -Body $bodyJSON -ContentType 'application/json'
Help me to update group chat post using PowerShell via graph api

graph api assign manager

I'm trying to assign the manager to a user in AAD the documentation says
PUT /users/{id}/manager/$ref
but i'm not sure what to feed the $ref variable. I've tried UPN and the ID, but I keep getting
The remote server returned an error: (400) Bad Request.
Here is how i'm trying to put the manager info, but clearly i'm not doing it right or I can't read the documentation from here
$Header = #{
Authorization = "$($Request.token_type) $($Request.access_token)"
}
$bodyProcess = #{
id= "string aa9999a1-1111-11a2-abab-asfdas32"
}
$body = $bodyProcess | ConvertTo-Json
$Uri = "https://graph.microsoft.com/v1.0/users/4d5f6c5a-0e69-40b6-a86d-e825582add50/manager/$ref"
$UserData = Invoke-RestMethod -Uri $Uri -Headers $Header -Method PUT -ContentType "application/json" -Body $Body
Any help would be greatly appreciated.
thanks,
Here is the full script that works for me.
$Header = #{
Authorization = "$($Request.token_type) $($Request.access_token)"
}
$bodyProcess = #{
"#odata.id"= "https://graph.microsoft.com/v1.0/users/aa9999a1-1111-11a2-abab-asfdas32"
}
$body = $bodyProcess | ConvertTo-Json
$Uri = 'https://graph.microsoft.com/v1.0/users/4d5f6c5a-0e69-40b6-a86d-e825582add50/manager/$ref'
Invoke-RestMethod -Uri $Uri -Headers $Header -Method PUT -ContentType "application/json" -Body $Body

Get all users under all projects from Azure DevOps

I am trying to get all users under couple of project. The case is that under users there are many and I need to to use continuationToken. The result is messy because my logic is bad. I cannot figure out how to use the second foreach..
$outputItems = #()
foreach ($project in $projects) {
$uriProjectDescriptor = "https://vssps.dev.azure.com/$OrganizationName/_apis/graph/descriptors/$($project.id)?api-version=5.0-preview.1"
$projectDescriptor = Invoke-RestMethod -Uri $uriProjectDescriptor -Method Get -Headers $AzureDevOpsAuthenicationHeader
$descriptors = $projectDescriptor.value
foreach ($descriptor in $descriptors) {
do
{
$uriUsers="https://vssps.dev.azure.com/$OrganizationName/_apis/graph/users?continuationToken=$continuationToken&scopeDescriptor=$($descriptor)&api-version=6.0-preview.1"
$responseUsers=Invoke-WebRequest -Uri $uriUser -Method Get -ContentType "application/json" -Headers $AzureDevOpsAuthenicationHeader -UseBasicParsing -MaximumRedirection 0
$continuationToken = $responseUsers.Headers.'x-ms-continuationtoken'
$userSet = $responseUsers.content | ConvertFrom-Json
$users += $userSet.value.Count
$arealList = New-Object -TypeName PSObject -Property #{
CountUsers = $users.Count
} | Select-Object "CountUsers"
$outputItems += $arealList
$arealList = $null
}
while (($continuationToken))
$ProgressPreference = 'Continue'
}
} $outputItems
You could try the following Powershell Script:
$token = "PAT"
$url="https://dev.azure.com/{Organizationname}/_apis/projects?api-version=6.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$responses = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach ($response in $responses.value.id)
{
$url1="https://vssps.dev.azure.com/{Organizationname}/_apis/graph/descriptors/$($response)?api-version=6.0-preview.1"
$Descriptor = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach ($Descriptor1 in $Descriptor.value)
{
do
{
$url2="https://vssps.dev.azure.com/{Organizationname}/_apis/graph/users?scopeDescriptor=$($Descriptor1)&api-version=6.0-preview.1"
$UserLists = Invoke-RestMethod -Uri $url2 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
$continuationToken = $UserLists.Headers.'x-ms-continuationtoken'
}
while ($continuationToken -ne $null)
Write-Host "result = $($UserLists | ConvertTo-Json -Depth 100)"
}
}
Explaination:
The first Rest API is used to get the Project name.
Then the second Rest API is used to get the descriptors.
The third Rest api is used to get the userlist.
I use foreach nesting to realize the loop of response to Rest API.
Update:
Test with the continuationToken and the maximum value of objects returned by a project is 500.
I found another Rest Api User Entitlements - List to get the users.
https://vsaex.dev.azure.com/Organization Name/_apis/userentitlements?top=10000&select=project&api-version=4.1-preview.1
This Rest APi could directly return the users under the organization(Project Scope). The max value is 10000.

Unlike postman, getting slow powershell script performance when used to interact with Microsoft Graph API

We are trying to use a PS script to start using Graph API:
$clientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXX"
$clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$TenantName = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$resource = "https://graph.microsoft.com/"
$URL = "https://graph.microsoft.com/v1.0/groups"
$tokenBody = #{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
Client_Id = $clientId
Client_Secret = $clientSecret
}
$tokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token" -Method POST -Body $tokenBody
$result = Invoke-RestMethod -Headers #{Authorization = "Bearer $($tokenResponse.access_token)"} -Uri $URL -Method Get -Verbose
($result | select-object Value).Value | Select-Object id
I am not sure if it is the script or something else but the success rate for this script is 20%. Most of the time the return is either delayed or timed out.
We are getting consistent results when we use postman to interact with the graph API. How come powershell is giving us a hard time? Is there something that we need to change on our script?
Thanks

how to translate curl command in powershell

I've this command:
curl -s -L --header "PRIVATE-TOKEN:XXXX" https://myuri/"
And I need to convert to PowerShell
I've tried this, but doesn't works:
Invoke-RestMethod -Method Get -Headers #{"AUTHORIZATION"="XXXXXX"} -Uri https://myUri
I've also tried this:
PS > $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
PS > $headers.Add("Authorization","XXXXXX")
PS > $headers.Add("Accept","application/json")
PS > $headers.Add("Content-Type","application/json")
PS> $uri = "https://myUri"
PS> $response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get -ContentType "application/json"
PS> $response
PS>
but the $response is empty.
Any help ?
Here is one that I used to authenticate to Teamcity
function Connect-to-Teamcity ($userName, $password, $tcServer, $uri)
{
$auth = $username + ':' + $password
$Encoded = [System.Text.Encoding]::UTF8.GetBytes($auth)
$EncodedPassword = [System.Convert]::ToBase64String($Encoded)
$headers = #{"Authorization"="Basic $($EncodedPassword)"}
$url = "http://$tcServer/httpAuth/app/rest"
$result = Invoke-RestMethod -Uri "$url/$uri" -Header $headers -Method Get
return $result
}
Here is another example if you have more than one header Item:
$resourceAppIdURI = "https://graph.windows.net"
# Login to Azure and get a token valid for accessing the graph API
$authority = "https://login.windows.net/$adTenant"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId, $redirectUri, "Auto")
# Add the token to the header of all future calls to the graph API
$headers = #{"Authorization"=$authResult.CreateAuthorizationHeader();"Content-Type"="application/json"}
$uri = [string]::Format("https://graph.windows.net/{0}/groups/{1}/appRoleAssignments?api-version=1.5", $adTenant, $groupId)
$body = #"
{
"id": $appRoleId,
"principalId": $groupId,
"principalType": "Group",
"resourceId": $appObjectId
}
"#
$result = Invoke-RestMethod -Method "POST" -Uri $uri -Headers $headers -Body $Body