PowerShell Entra users and groups
Managing Entra ID users and groups through Graph works, with a few sharp edges worth knowing before you write a script that changes things.
Documentation: Microsoft Learn
Overview
Synchronised objects cannot be edited in the cloud. A user with OnPremisesSyncEnabled set to true is mastered in on-premises AD, and Update-MgUser on their attributes either fails or is overwritten at the next sync cycle. Check that property before writing anything, and make the change in AD instead.
Group membership depends on the group type. A dynamic group's membership comes from a rule, so Add-MgGroupMember on it is refused. Assigned groups accept explicit members. Mail-enabled security groups are managed through Exchange Online rather than Graph. So the right cmdlet depends on the group, which is why inspecting groupTypes first matters.
Graph filter syntax is OData, not PowerShell and not AD. It uses eq rather than -eq, and constructs like groupTypes/any(...) for collections. Some filters need -ConsistencyLevel eventual together with -CountVariable, which the error message will tell you.
Deleted users go to a recycle bin for 30 days and are restorable, which is a useful thing to know before you panic about a bulk operation.
Licence assignment moved: Set-MgUserLicense is the current cmdlet, and group-based licensing is the better approach at scale.
Inspect this example’s structure
Read the command and its supplied arguments. This example requires real PowerShell or its module; this diagram does not execute it.
[pscustomobject]@{
Users = 'Get-MgUser -All -Property DisplayName,UserPrincipalName,AccountEnabled,OnPremisesSyncEnabled'
Groups = 'Get-MgGroup -Filter "groupTypes/any(c:c eq ''DynamicMembership'')"'
Members = 'Get-MgGroupMember -GroupId <id> -All'
Licences = 'Get-MgUserLicenseDetail -UserId <upn>'
} | Format-List- Stage 1[pscustomobject]@{
Positional values or no named parameters - Stage 2Format-List
Positional values or no named parameters
An example to inspect
Preview the example. Sign in for the full lesson and activities.
[pscustomobject]@{
Users = 'Get-MgUser -All -Property DisplayName,UserPrincipalName,AccountEnabled,OnPremisesSyncEnabled'
Groups = 'Get-MgGroup -Filter "groupTypes/any(c:c eq ''DynamicMembership'')"'
Members = 'Get-MgGroupMember -GroupId <id> -All'
Licences = 'Get-MgUserLicenseDetail -UserId <upn>'
} | Format-ListWhat happens
This prints four queries. The first includes OnPremisesSyncEnabled deliberately, because that single property tells you whether the object is yours to edit. The second uses OData collection syntax to find dynamic groups, which are the ones that will reject a membership change.
Worth remembering
- OnPremisesSyncEnabled means the object is mastered in on-premises AD.
- Dynamic groups reject explicit membership changes.
- Graph filters are OData: eq, not -eq.
- Deleted users are restorable for 30 days.
Primary documentation
Try it
Expected output · prints command text; does not execute these commands
[pscustomobject]@{ Users = 'Get-MgUser -All -Property DisplayName,UserPrincipalName,AccountEnabled,OnPremisesSyncEnabled' Groups = 'Get-MgGroup -Filter "groupTypes/any(c:c eq ''DynamicMembership'')"' Members = 'Get-MgGroupMember -GroupId <id> -All' Licences = 'Get-MgUserLicenseDetail -UserId <upn>'} | Format-ListExample reader
Inspect this page's example
Run supported commands against the practice data, or inspect the example without executing it.
Ready to inspect.
Prints Entra queries, including the sync-status check that gates edits.
Show reference output
Expected output · prints command text; does not execute these commands
Users : Get-MgUser -All -Property DisplayName,UserPrincipalName,AccountEnabled,OnPremisesSyncEnabled Groups : Get-MgGroup -Filter "groupTypes/any(c:c eq 'DynamicMembership')" Members : Get-MgGroupMember -GroupId <id> -All Licences : Get-MgUserLicenseDetail -UserId <upn>
Practise this
Find disabled cloud accounts
Connect to the fictional tenant first. Request AccountEnabled and return DisplayName, UserPrincipalName and AccountEnabled for disabled users.
The sandbox is visible now. Sign in with Google only when you run or check a task; commands and temporary files are discarded when you leave.
Run a command to inspect its result.
Inspect starting data
Supported syntax
Virtual files
Keep going
Next: Exchange Online PowerShellCheck your understanding
A user query omits a property you need. Does that prove the directory value is empty?
No. Request the property explicitly, check permissions and inspect the returned object before deciding that the stored value is empty.