Adding a user to a Microsoft Entra group is a common administrative task. It can be done through the Microsoft Entra admin center, but PowerShell is more useful when the operation needs to be repeated or included in an automation workflow.
In this article, we will use the Microsoft Graph PowerShell SDK to add a user to an existing Microsoft Entra group.
The process is straightforward:
Prerequisites
Before running the examples, make sure you have:
- Access to a Microsoft Entra tenant.
- Permission to modify the target group’s membership.
- Microsoft Graph PowerShell installed.
- The user’s UPN or Object ID.
- The target group’s Object ID or display name.
This article uses delegated authentication, where PowerShell connects to Microsoft Graph using your signed-in administrator account.
Microsoft Graph PowerShell supports both delegated and application authentication. Connect-MgGraph is used to establish the Graph connection before running Graph commands.
Install Microsoft Graph PowerShell
If the Microsoft Graph PowerShell SDK is not installed, run:
Install-Module Microsoft.Graph -Scope CurrentUserIf the module is already installed, you can check its version:
Get-InstalledModule Microsoft.GraphYou can also install only the modules required for this task:
Install-Module Microsoft.Graph.Authentication -Scope CurrentUser
Install-Module Microsoft.Graph.Groups -Scope CurrentUser
Install-Module Microsoft.Graph.Users -Scope CurrentUserFor most administrator workstations, installing the complete Microsoft.Graph SDK is convenient. For tightly controlled automation environments, installing only the required modules can reduce the footprint.
Connect to Microsoft Graph
For an interactive PowerShell session, connect using:
Connect-MgGraph -Scopes "GroupMember.ReadWrite.All"A browser authentication window will appear.
After authentication, verify the connection:
Get-MgContextYou can also check the permissions granted to the current session:
(Get-MgContext).ScopesYou should see:
GroupMember.ReadWrite.All
The permission is important because adding a user changes the membership of the group.
Microsoft documents GroupMember.ReadWrite.All as the least-privileged delegated permission for adding a user to a group through the Graph API.
Important: Graph Permission Is Not the Only Requirement
Having the Graph permission does not automatically mean every user can modify every group.
In delegated authentication, the signed-in user must also have a supported Microsoft Entra role or a custom role containing the required group-membership update permission.
Microsoft currently lists roles including:
- Group owner
- Directory Writers
- Groups Administrator
- Identity Governance Administrator
- User Administrator
For security groups, Intune Administrator is also listed as a supported role.
This is an important distinction when troubleshooting 403 Forbidden errors.
Find the Microsoft Entra Group
Suppose we have a group called:
Intune-Windows-11-Pilot-Users
We can search for it using:
$group = Get-MgGroup -Filter "displayName eq 'Intune-Windows-11-Pilot-Users'"Display the result:
$group | Select-Object Id, DisplayName, GroupTypes, SecurityEnabled, MailEnabledThe important property is:
$group.Id
For example:
The Id is the group’s Microsoft Entra Object ID.
Validate the Group
A production script should not assume that the group exists.
For example:
$groups = Get-MgGroup -Filter "displayName eq 'Intune-Windows-11-Pilot-Users'"
if (-not $groups) {
throw "Group was not found."
}
if (@($groups).Count -gt 1) {
throw "Multiple groups were found with this display name."
}
$group = $groups[0]This prevents the script from accidentally operating against an unexpected group.
Using the group’s Object ID directly is even better when you already know it:
$groupId = "a1234567-89ab-cdef-0123-456789abcdef"
Object IDs are preferable for production automation because display names can change.
Find the User
Now suppose we want to add:
alex@contoso.com
We can retrieve the user with:
$user = Get-MgUser -UserId "alex@contoso.com"
Display the important properties:
$user | Select-Object Id, DisplayName, UserPrincipalName
Example:
Id DisplayName UserPrincipalName
-- ----------- -----------------
b2345678-90ab-cdef-0123-456789abcdef Alex Smithalex@contoso.com
Again, the important value is:
$user.Id
This is the user’s Microsoft Entra Object ID.
Why Do We Need the Object ID?
This is one of the most important concepts in the process.
You might know the user as:
alex@contoso.com
But the group membership API works with a directory object reference.
The Graph request ultimately looks like:
POST /groups/{group-id}/members/$ref
and the request body contains a reference to the directory object:
{
"@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/{user-object-id}"
}
Microsoft documents this exact @odata.id approach for New-MgGroupMemberByRef.
So the PowerShell workflow is:
UserPrincipalName
↓
Get-MgUser
↓
User Object ID
↓
@odata.id
↓
New-MgGroupMemberByRef
Add the User to the Group
Now that we have both IDs, create the membership reference:
$params = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$($user.Id)"
}
Then add the user:
New-MgGroupMemberByRef `
-GroupId $group.Id `
-BodyParameter $params
That’s the actual operation that adds the user to the group.
Microsoft’s PowerShell documentation uses the same New-MgGroupMemberByRef cmdlet and @odata.id directory object reference.
Complete Example
Here is the complete script in one place:
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "GroupMember.ReadWrite.All"
# Variables
$groupName = "Intune-Windows-11-Pilot-Users"
$userUPN = "alex@contoso.com"
# Find the group
$groups = Get-MgGroup `
-Filter "displayName eq '$groupName'"
if (-not $groups) {
throw "Group '$groupName' was not found."
}
if (@($groups).Count -gt 1) {
throw "Multiple groups found with the name '$groupName'."
}
$group = $groups[0]
# Find the user
$user = Get-MgUser -UserId $userUPN
if (-not $user) {
throw "User '$userUPN' was not found."
}
# Create the directory object reference
$params = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$($user.Id)"
}
# Add the user to the group
New-MgGroupMemberByRef `
-GroupId $group.Id `
-BodyParameter $params
Write-Host "User '$userUPN' was added to '$groupName'."
Verify the User Was Added
After performing the operation, it is a good idea to verify the membership.
You can retrieve the group’s direct members:
Get-MgGroupMember -GroupId $group.Id -All
However, this normally gives you directory objects rather than a convenient user list.
For a simple check, compare the user’s Object ID against the returned members:
$members = Get-MgGroupMember -GroupId $group.Id -All
if ($members.Id -contains $user.Id) {
Write-Host "User is a member of the group."
}
else {
Write-Host "User is not a member of the group."
}
Microsoft documents this operation as returning the group’s direct members. It does not perform transitive membership evaluation through nested groups.
What If the User Is Already a Member?
This is an important consideration when turning the script into automation.
Before adding the user, check whether the user is already a direct member:
$members = Get-MgGroupMember `
-GroupId $group.Id `
-All
if ($members.Id -contains $user.Id) {
Write-Host "$userUPN is already a member."
}
else {
$params = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$($user.Id)"
}
New-MgGroupMemberByRef `
-GroupId $group.Id `
-BodyParameter $params
Write-Host "$userUPN was added successfully."
}
This makes the script idempotent.
In simple terms, you can run it multiple times without intentionally trying to add the same user again.
This becomes particularly useful when the script is later integrated with:
- Intune automation
- ServiceNow workflows
- Azure Automation
- Scheduled PowerShell jobs
- User onboarding processes
- Application deployment workflows
A Reusable Function
If you regularly perform this operation, create a function:
function Add-EntraGroupUser {
param (
[Parameter(Mandatory)]
[string]$GroupId,
[Parameter(Mandatory)]
[string]$UserId
)
$members = Get-MgGroupMember `
-GroupId $GroupId `
-All
if ($members.Id -contains $UserId) {
Write-Host "User is already a member."
return
}
$params = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$UserId"
}
New-MgGroupMemberByRef `
-GroupId $GroupId `
-BodyParameter $params
Write-Host "User added successfully."
}
You can then call:
Add-EntraGroupUser `
-GroupId "a1234567-89ab-cdef-0123-456789abcdef" `
-UserId "b2345678-90ab-cdef-0123-456789abcdef"
This is useful when the user and group IDs are already available from another automation system.
Common Errors
1. Insufficient privileges
You may see an error similar to:
Insufficient privileges to complete the operation.
First check your Graph scopes:
(Get-MgContext).Scopes
Make sure the required permission is present:
GroupMember.ReadWrite.All
Then verify that the signed-in account has an appropriate Microsoft Entra role.
Microsoft specifically notes that both Graph permissions and an appropriate directory role matter for delegated access.
2. 403 Forbidden
A 403 Forbidden response generally means the authenticated identity is not authorized to perform the operation.
Check:
Get-MgContext
Then verify:
- Correct tenant.
- Required Graph permission.
- Admin consent where required.
- Appropriate Entra role.
- Target group type.
- Whether the group is role-assignable.
Role-assignable groups have additional requirements. Microsoft documents RoleManagement.ReadWrite.Directory as an additional application/delegated permission requirement for adding members to role-assignable groups, along with the appropriate privileged role.
3. Group not found
If this returns nothing:
Get-MgGroup -Filter "displayName eq 'My Group'"
check the exact group name.
You can also search groups:
Get-MgGroup -Filter "startswith(displayName,'Intune')"
For production scripts, using the Object ID is preferable when it is already known.
4. User not found
Check the UPN:
Get-MgUser -UserId "alex@contoso.com"
If necessary, search using the display name or UPN:
Get-MgUser `
-Filter "userPrincipalName eq 'alex@contoso.com'"
Make sure you are connected to the correct tenant:
(Get-MgContext).TenantId
Security Considerations
Group membership can have significant consequences.
An Entra group might be used for:
- Intune application assignments.
- Configuration policies.
- Conditional Access.
- Microsoft 365 resources.
- Security permissions.
- Administrative role assignments.
Therefore, scripts that modify group membership should be treated as privileged automation.
Use the least privilege required for the operation and avoid storing passwords, access tokens, or client secrets directly in scripts.
For interactive administration, delegated authentication with Connect-MgGraph is usually sufficient.
For unattended automation, Microsoft Graph also supports application authentication, including certificate-based authentication and managed identities. Microsoft recommends secure authentication approaches rather than embedding credentials in scripts.
Summary
Adding a user to a Microsoft Entra group with PowerShell requires only a few steps:
Connect-MgGraph
Find the group:
$group = Get-MgGroup -Filter "displayName eq 'My Group'"
Find the user:
$user = Get-MgUser -UserId "user@contoso.com"
Create the directory object reference:
$params = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$($user.Id)"
}
Add the user:
New-MgGroupMemberByRef `
-GroupId $group.Id `
-BodyParameter $params
The key concept is that the group membership operation uses the user’s Microsoft Entra Object ID, not the user’s UPN.
Once this basic operation is understood, the same approach can be extended to bulk user assignments, device membership, and automated Intune group management.
References
- Microsoft Learn — New-MgGroupMemberByRef
New-MgGroupMemberByRef
Used for the PowerShell cmdlet syntax and @odata.id membership reference. - Microsoft Graph — Add members to a group
Add members to a group
Used for Graph API behavior, permissions, supported member types, and role requirements. - Microsoft Learn — Microsoft Graph PowerShell authentication
Use Microsoft Graph PowerShell authentication commands
Used for Connect-MgGraph, delegated authentication, and app-only authentication. - Microsoft Learn — Get-MgGroupMemberByRef
Get-MgGroupMemberByRef
Used for direct group-membership verification behavior.
Suggested next posts
The natural follow-up is “How to Add a Device to a Microsoft Entra Group Using PowerShell”, where we can explain the important difference between Entra Device ID and Object ID. After that, we can cover bulk adding users from CSV.
