Graph API and Microsoft Graph SDK module tips & gotchas
Table of contents
- Gotchas
- Returned object properties can be CASE SENSITIVE ๐ช
- Documentation is terrible
- A lot of commands don't support pipeline?!
- Official 'Microsoft Graph PowerShell' Azure application isn't verified
- There is a bug whereevery single cmdlet requests another authentication prompt
- CmdletInvoke-MgGraphRequestdoesn't manage paging! So not all results will be returned at once and you need to solve this on your own
- Graph cmdlets return all results only ifAllparameter is used!
- When you connect using a certificate and later in your code calls Connect-MgGraph it will display interactive auth. prompt
- Cmdlet Connect-MgGraph doesn't support the use of saved credentials
- Cmdlets don't have to return all property values by default
- It's not obvious whether property or expandProperty parameter should be used to get the property data
- Some commands return properties that will be always empty
- Tips
- How to identify AzureAD and MSOnline deprecated modules usage in your scripts and get corresponding Graph commands
- Always have all your Microsoft.Graph.* modules in the same version!
- Some cmdlets need switching to the BETA version of the API for it to work (for exampleInvoke-MgInvalidateUserRefreshToken)
- Cmdlets with switch-type parameters should use a colon to pass the switch value
- Run Graph cmdlets withdebugparameter to get more detailed information and called URI
- Getting Graph command that works with specific API URI
- Getting Graph URI that is used by the specific command
- You should explicitly specify required scopes (permissions) when connecting to Graph API
- Getting Graph permission required for a specific command
- Use Format-Custom to expand the returned object's properties
- Filter query operatorsne,not,endsWithneeds to haveConsistencyLevel = 'Eventual'parameter set
- Filter query operatorsne,not,endsWithcan be used only on some types of objects
- For directory objects like users, thenotandneoperators are supported only in advanced queries
- Find all Graph modules required to run selected code (and its dependencies)
Several weeks ago I started to migrate our PowerShell scripts from using soon-to-be-deprecated AzureAD and MSOnline modules and replace them with the Microsoft Graph SDK module.
During this time I came across various gotchas that I will summarize in this short post.
This post is from 9.2.2023 and is referring to Graph modules of 1.20.0 version, but most of the mentioned info still apply for 2.x versions unfortunately.
Gotchas
Returned object properties can be CASE SENSITIVE ๐ช
-
For example cmdlet
Get-MgDirectoryObjectById
. The funny thing is that just the object saved in the property AdditionalProperties has case-sensitive properties. The main object properties aren't case sensitive ๐
Documentation is terrible
It lacks examples. Especially unfortunate when an object has to be passed as an argument and you have no idea what it should look like.
It is crazy big (so it is super hard to find what you are looking for)
It is missing the description of the parameters
A lot of commands don't support pipeline?!
Like why can't I pass the output of the Get-MgUser
to the Update-MgUser
?!
Official 'Microsoft Graph PowerShell' Azure application isn't verified
If connecting to Graph API using
Connect-MgGraph
with the new permission scope (you will have to grant consent), you will see a popup like below that shows the official Microsoft Graph PowerShell application as unverified. WTF Microsoft?!
There is a bug whereevery single cmdlet requests another authentication prompt
- To fix this run:
Remove-Item "$env:USERPROFILE\.graph" -Recurse -Force
to clean the cache
CmdletInvoke-MgGraphRequest
doesn't manage paging! So not all results will be returned at once and you need to solve this on your own
- Just the first 100 or so items will be returned (because of paging)
Graph cmdlets return all results only ifAll
parameter is used!
- Without
All
parameter just the first 100 or so items will be returned (because of paging)
When you connect using a certificate and later in your code calls Connect-MgGraph it will display interactive auth. prompt
But if you connect using saved credentials, no following prompts will be shown
This super complicates unattended scripting. In such case, you probably use service principal and authenticate using a certificate. But if such script calls any function or script that again calls Connect-MgGraph (because it is convenient to start your Graph code by making a connection), it will timeout/error.
Cmdlet Connect-MgGraph doesn't support the use of saved credentials
I've solved this by passing AccessToken
The new v2.x module version is fine though
Cmdlets don't have to return all property values by default
The object with all available properties is always returned, but not all properties will be populated
The properties you want to retrieve can be specified by the
Property
parameter (Get-MgUser -Property DisplayName, Id
) or parameterExpandProperty
if the property is expandable. Using a wildcard*
isn't supported (but there is a workaround).
It's not obvious whether property
or expandProperty
parameter should be used to get the property data
- For example
Get-MgGroup
command returns property Owners only ifexpandProperty
parameter will be used! If you call it likeGet-MgGroup -property owners
, there will be no error, but also the owner's property will be always empty no matter what! See this github issue.
Some commands return properties that will be always empty
For example Get-MgGroup
returns property MembersWithLicenseErrors
which is always empty because it is a relationship property and you have to use the command Get-MgGroupMemberWithLicenseError
instead to get this data ๐
Tips
How to identify AzureAD and MSOnline deprecated modules usage in your scripts and get corresponding Graph commands
- Check my post to get results like this ๐
Always have all your Microsoft.Graph.* modules in the same version!
A.k.a. Microsoft.Graph.Authentication, Microsoft.Graph.Applications, ... in 1.20.0 version for example
Otherwise, you will see strange errors when trying to import a module with a different version
Some cmdlets need switching to the BETA version of the API for it to work (for exampleInvoke-MgInvalidateUserRefreshToken
)
v1.x
Call
Select-MgProfile -Name Beta
beforeInvoke-MgInvalidateUserRefreshToken
But don't forget to reverse to the stable API version ASAP!
v2.x
- call
Invoke-MgBetaInvalidateUserRefreshToken
instead
- call
Cmdlets with switch-type parameters should use a colon to pass the switch value
- A.k.a.
New-MgInvitation -InvitedUserDisplayName $displayName -SendInvitationMessage:$true
Run Graph cmdlets withdebug
parameter to get more detailed information and called URI
Getting Graph command that works with specific API URI
Find-MgGraphCommand -Uri
https://graph.microsoft.com/v1.0/deviceManagement
| Select-ObjectCommand
Getting Graph URI that is used by the specific command
Find-MgGraphCommand -Command Get-MgUser | Select-Object URI
Use Chrome addon https://graphxray.merill.net
Open the Azure or Intune page where the results you are interested in are shown >> press F12 to open Developer Tools >> switch to Network tab >> search for graph.microsoft.com in the results
You should explicitly specify required scopes (permissions) when connecting to Graph API
Connect-MgGraph -Scopes '
DeviceManagementManagedDevices.Read
.All'
How to find those scopes is mentioned later in this list
Getting Graph permission required for a specific command
Find-MgGraphCommand -Command Get-MgUser | Select-Object Permissions
Find-MgGraphPermission -SearchString read
How to get all permissions required by selected code (and its dependencies)
Use Format-Custom
to expand the returned object's properties
Get-MgUser -Top 1 | Format-Custom
Will expand the object properties so you will get a better understanding about the while object
Filter query operatorsne
,not
,endsWith
needs to haveConsistencyLevel = 'Eventual'
parameter set
Filter query operatorsne
,not
,endsWith
can be used only on some types of objects
For directory objects like users, thenot
andne
operators are supported only in advanced queries
- A.k.a.
consistencyLevel
parameter has to be specified
Find all Graph modules required to run selected code (and its dependencies)
Subscribe to my newsletter
Read articles from Ondrej Sebela directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Ondrej Sebela
Ondrej Sebela
I work as System Administrator for more than 10 years now and I love to make my life easier by automating work & personal stuff via PowerShell (even silly things like food recipes list generation).