# Graph API and Microsoft Graph SDK module tips & gotchas

Several weeks ago I started to [migrate our PowerShell scripts](https://doitpsway.com/how-to-find-and-replace-commands-from-azuread-and-msonline-deprecated-modules-in-your-scripts-for-the-graph-ones) from using soon-to-be-deprecated **AzureAD** and **MSOnline** modules and replace them with the [Microsoft Graph SDK](https://learn.microsoft.com/en-us/graph/sdks/sdk-installation#install-the-microsoft-graph-powershell-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 🪓**

* ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1675952040146/44a52f52-c614-4ec5-b53e-70e405a95ce3.png align="center")
    
    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](https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.groups/update-mggroup?view=graph-powershell-1.0) (so it is super hard to find what you are looking for)
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1675957577528/767a4f0e-37f6-4ff3-9fa9-af18b17754f1.png align="center")
    
* It is [missing](https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.directoryobjects/get-mgdirectoryobjectbyid?view=graph-powershell-1.0) the description of the parameters
    
* ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1675957627617/caa6b724-bbff-4192-b835-239f137990b0.png align="center")
    

### **A lot of commands don't support pipeline?!**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1675968370057/d831e003-01bb-48c2-b65e-80f1908cf4bb.png align="center")

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?!
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1679047587580/27872ad8-70e1-4d02-a747-13b746a59a0b.png align="center")
    

### **There is a bug where**[**every single cmdlet requests another authentication prompt**](https://github.com/microsoftgraph/msgraph-sdk-powershell/issues/851)

* To fix this run: `Remove-Item "$env:USERPROFILE\.graph" -Recurse -Force` to clean the cache
    

### **Cmdlet**`Invoke-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 if**`All`**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](https://doitpsway.com/how-to-connect-to-the-microsoft-graph-api-using-saved-user-credentials)
    
* 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 parameter `ExpandProperty` if the property is expandable. Using a **wildcard**`*`**isn't supported** (but there is a [workaround](https://doitpshway.com/adding-support-for-selecting-all-properties-using-wildcard-in-mg-graph-commands-property-parameter)).
    

### 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 if `expandProperty` parameter will be used! If you call it like `Get-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](https://github.com/microsoftgraph/msgraph-sdk-powershell/issues/1846).
    

### 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](https://github.com/microsoftgraph/msgraph-sdk-powershell/issues/1878#issuecomment-1472857291) 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](https://doitpsway.com/how-to-find-and-replace-commands-from-azuread-and-msonline-deprecated-modules-in-your-scripts-for-the-graph-ones) to get results like this 👇
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1675957404893/2a5425ce-bd0a-42e0-959e-f6fe11ec3f02.png align="left")

### **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 example**`Invoke-MgInvalidateUserRefreshToken`**)**

* v1.x
    
    * Call `Select-MgProfile -Name Beta` before `Invoke-MgInvalidateUserRefreshToken`
        
    * But don't forget to reverse to the stable API version ASAP!
        
* v2.x
    
    * call `Invoke-MgBetaInvalidateUserRefreshToken` instead
        

### **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 with**`debug`**parameter to get more detailed information and called URI**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1675956982944/81db6cc1-b855-4d89-80e1-089801acddeb.png align="center")

### **Getting Graph command that works with specific API URI**

* `Find-MgGraphCommand -Uri`[`https://graph.microsoft.com/v1.0/deviceManagement`](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](https://graphxray.merill.net)
    
* Open the Azure or Intune page where the results you are interested in are shown &gt;&gt; press **F12** to open Developer Tools &gt;&gt; switch to **Network** tab &gt;&gt; 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`](http://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)](https://doitpshway.com/how-to-get-all-graph-api-permissions-required-to-run-selected-code-using-powershell)
    

### **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 operators**`ne`**,**`not`**,**`endsWith`**needs to have**`ConsistencyLevel = 'Eventual'`**parameter set**

* [https://learn.microsoft.com/en-us/graph/aad-advanced-queries?tabs=http](https://learn.microsoft.com/en-us/graph/aad-advanced-queries?tabs=http)
    

### **Filter query operators**`ne`**,**`not`**,**`endsWith`**can be used only on some types of objects**

* [https://learn.microsoft.com/en-us/graph/aad-advanced-queries?tabs=http](https://learn.microsoft.com/en-us/graph/aad-advanced-queries?tabs=http)
    

### **For directory objects like users, the**`not`**and**`ne`**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)

[https://doitpshway.com/how-to-get-all-graph-powershell-sdk-modules-required-to-run-selected-code-using-powershell](https://doitpshway.com/how-to-get-all-graph-powershell-sdk-modules-required-to-run-selected-code-using-powershell)
