Skip to content

Commit a892cc5

Browse files
authored
Merge pull request #7964 from MicrosoftDocs/main
Auto push to live 2025-01-02 02:00:02
2 parents 40920d3 + 8eb38eb commit a892cc5

3 files changed

Lines changed: 140 additions & 1 deletion

File tree

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
title: Handling errors in Microsoft Graph API requests with invoke-restmethod
3+
description: This article provides a code sample to simulate a handling error that occurs when you make requests to the Microsoft Graph API by using the Invoke-RestMethod cmdlet in PowerShell.
4+
ms.date: 02/18/2024
5+
author: genlin
6+
ms.author: raheld
7+
ms.service: entra-id
8+
ms.topic: overview
9+
content_well_notification: AI-contribution
10+
ai-usage: ai-assisted
11+
ms.custom: sap:Microsoft Graph Users, Groups, and Entra APIs
12+
---
13+
# Handling errors in Microsoft Graph API Requests with Invoke-RestMethod
14+
15+
This article provides a code sample that demonstrates how to handle errors and implement retry logic when you make requests to the Microsoft Graph API by using the `Invoke-RestMethod` cmdlet in PowerShell.
16+
17+
## Prerequisites
18+
19+
- An Azure app registration with a client secret
20+
- The `user.read.all` permission for Microsoft.Graph for the Azure app. For more information, see [List users](/graph/api/user-get?view=graph-rest-1.0&tabs=http&preserve-view=true).
21+
22+
## Code sample
23+
24+
To demonstrate the retry logic, this sample tries to query the `signInActivity` data for guest users. When you run this code, you can expect to receive a "403" error.
25+
26+
- **Get-AccessTokenCC** This function requests an access token from Microsoft Entra ID (formerly Azure Active Directory). The token will be used to authenticate API requests to Microsoft Graph. You have to provide values for the `$clientSecret`, `$clientId`, and `$tenantId` variables of your Azure registration app.
27+
- **Get-GraphQueryOutput ($Uri)** This function makes a request to the Microsoft Graph API to retrieve data. It also handles paging. The function retries the request if a "403" error is generated.
28+
29+
``` powershell
30+
Function Get-AccessTokenCC
31+
32+
{
33+
$clientSecret = ''
34+
$clientId = ''
35+
$tenantId = ''
36+
# Construct URI
37+
$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
38+
# Construct Body
39+
$body = @{
40+
client_id = $clientId
41+
client_secret = $clientSecret
42+
scope = 'https://graph.microsoft.com/.default'
43+
grant_type = 'client_credentials'
44+
}
45+
# Get OAuth 2.0 Token
46+
$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType 'application/x-www-form-urlencoded' -Body $body -UseBasicParsing
47+
# Access Token
48+
$token = ($tokenRequest.Content | ConvertFrom-Json).access_token
49+
#$token = "Junk" #uncomment this line to cause a 401 error -- you can set that status in the error handler to test the pause and retry
50+
#Write-Host "access_token = $token"
51+
return $token
52+
}
53+
54+
Function Get-GraphQueryOutput ($Uri)
55+
{
56+
write-host "uri = $Uri"
57+
write-host "token = $token"
58+
59+
$retryCount = 0
60+
$maxRetries = 3
61+
$pauseDuration = 2
62+
63+
$allRecords = @()
64+
while ($Uri -ne $null){
65+
Write-Host $Uri
66+
try {
67+
# todo: verify that the bearer token is still good -- hasn't expired yet -- if it has, then get a new token before making the request
68+
$result=Invoke-RestMethod -Method Get -Uri $Uri -ContentType 'application/json' -Headers @{Authorization = "Bearer $token"}
69+
70+
Write-Host $result
71+
72+
if($query.'@odata.nextLink'){
73+
# set the url to get the next page of records. For more information about paging, see https://docs.microsoft.com/graph/paging
74+
$Uri = $query.'@odata.nextLink'
75+
} else {
76+
$Uri = $null
77+
}
78+
79+
} catch {
80+
Write-Host "StatusCode: " $_.Exception.Response.StatusCode.value__
81+
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
82+
83+
if($_.ErrorDetails.Message){
84+
Write-Host "Inner Error: $_.ErrorDetails.Message"
85+
}
86+
87+
# check for a specific error so that we can retry the request otherwise, set the url to null so that we fall out of the loop
88+
if($_.Exception.Response.StatusCode.value__ -eq 403 ){
89+
# just ignore, leave the url the same to retry but pause first
90+
if($retryCount -ge $maxRetries){
91+
# not going to retry again
92+
$Uri = $null
93+
Write-Host 'Not going to retry...'
94+
} else {
95+
$retryCount += 1
96+
Write-Host "Retry attempt $retryCount after a $pauseDuration second pause..."
97+
Start-Sleep -Seconds $pauseDuration
98+
}
99+
100+
} else {
101+
# not going to retry -- set the url to null to fall back out of the while loop
102+
$Uri = $null
103+
}
104+
}
105+
}
106+
107+
$output = $allRecords | ConvertTo-Json
108+
109+
if ($result.PSObject.Properties.Name -contains "value") {
110+
return $result.value
111+
} else {
112+
return $result
113+
}
114+
}
115+
116+
# Graph API URIs
117+
$uri = 'https://graph.microsoft.com/v1.0/users?$filter=userType eq ''Guest''&$select=displayName,UserprincipalName,userType,identities,signInActivity'
118+
119+
# Pull Data
120+
$token = Get-AccessTokenCC
121+
Get-GraphQueryOutput -Uri $uri|out-file c:\\temp\\output.json
122+
123+
```
124+
125+
## Capturing a specific header
126+
127+
For advanced scenarios, such as capturing specific header values such as `Retry-After` during throttling responses (HTTP 429), use:
128+
129+
```powershell
130+
$retryAfterValue = $_.Exception.Response.Headers["Retry-After"]
131+
```
132+
To handle the "429 - too many requests" error, see [Microsoft Graph throttling guidance](/graph/throttling).
133+
134+
[!INCLUDE [Azure Help Support](../../../includes/azure-help-support.md)]
135+

support/entra/entra-id/toc.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,9 @@
232232
href: mfa/cannot-verify-account-reset-pwd.md
233233
- name: Microsoft Graph Users, Groups, and Entra APIs
234234
items:
235-
- name: Troubleshoot Authorization_RequestDenied error
235+
- name: Handling errors in Graph API requests with Invoke-RestMethod
236+
href: app-integration/graph-api-error-handling-invoke-restmethod.md
237+
- name: Troubleshoot Authorization RequestDenied error
236238
href: app-integration/troubleshoot-authorization-requestdenied-graph-api.md
237239
- name: Microsoft Entra User Provisioning and Synchronization
238240
items:

support/windows-server/active-directory/manually-remove-lingering-objects.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ ms.custom: sap:Active Directory\Active Directory replication and topology, csstr
1212

1313
This article helps manually remove [lingering objects](information-lingering-objects.md#summary) after you bring an outdated domain controller (DC) or global catalog server back online. In many cases, you can clean up lingering objects using the `repadmin /removelingeringobjects` command or tools like [Lingering Object Liquidator](lingering-object-liquidator-tool.md). However, these facilities don't work if you have [abandoned objects](https://support.microsoft.com/topic/attributes-that-contain-stale-or-bad-data-cause-exchange-offline-address-book-oab-generation-failures-and-event-ids-9126-9330-and-9339-together-with-stop-error-code-8004010e-occur-d505154b-f51f-6604-436b-e30fe4e486d9).
1414

15+
_Original KB number:_   314282
16+
1517
When you bring a domain controller or global catalog server back online after it has been offline for a long time, any of the following issues might occur:
1618

1719
- Email messages aren't delivered to a user whose user object was moved between domains. After you bring the outdated domain controller or global catalog server back online, both instances of the user object appear in the global catalog content. Both objects have the same email address, so email messages can't be delivered.

0 commit comments

Comments
 (0)