Skip to main content
Microsoft Graph is the unified API for accessing Microsoft 365 services. The Microsoft.Graph PowerShell SDK wraps Graph API calls as native PowerShell cmdlets, making it the recommended approach for all modern Microsoft 365 automation.

Installing the module

# Install the full SDK (includes all service modules)
Install-Module -Name Microsoft.Graph -Force

# Install only the modules you need (faster, smaller footprint)
Install-Module -Name Microsoft.Graph.Users -Force
Install-Module -Name Microsoft.Graph.Groups -Force
Install-Module -Name Microsoft.Graph.Mail -Force
Install-Module -Name Microsoft.Graph.Sites -Force
Install-Module -Name Microsoft.Graph.Teams -Force
Install-Module -Name Microsoft.Graph.Identity.SignIns -Force

# Check the installed version
Get-InstalledModule -Name Microsoft.Graph | Select-Object Name, Version
Installing individual sub-modules instead of the full Microsoft.Graph bundle significantly reduces installation time and import overhead. You can always add more sub-modules later.

Authentication

Microsoft Graph uses OAuth 2.0. The Connect-MgGraph cmdlet handles the authentication flow.
# Interactive login with specific permission scopes
Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All", "Mail.Read"

# Check current connection context
Get-MgContext

# Disconnect
Disconnect-MgGraph

Application (non-interactive) authentication

For scheduled tasks and automation scripts that run unattended, authenticate as an app registration rather than a user.
# Connect using a client secret (app registration)
$ClientId     = "your-app-client-id"
$TenantId     = "your-tenant-id"
$ClientSecret = "your-client-secret" | ConvertTo-SecureString -AsPlainText -Force

$Credential = New-Object System.Management.Automation.PSCredential($ClientId, $ClientSecret)

Connect-MgGraph -TenantId $TenantId -ClientSecretCredential $Credential

# Connect using a certificate (more secure than client secret)
Connect-MgGraph -TenantId $TenantId -ClientId $ClientId -CertificateThumbprint "ABC123..."
Application authentication grants the permissions assigned to the app registration in Azure Portal > App registrations > API permissions. These are application permissions, not delegated permissions.

Common cmdlet patterns

All Graph cmdlets follow consistent naming conventions based on the HTTP verbs used by the underlying REST API.
PrefixHTTP methodExample
Get-Mg*GETGet-MgUser, Get-MgGroup
New-Mg*POSTNew-MgUser, New-MgGroup
Update-Mg*PATCHUpdate-MgUser, Update-MgGroup
Remove-Mg*DELETERemove-MgUser, Remove-MgGroup
Invoke-MgGraph*AnyDirect API calls with custom payloads
# Get operations
Get-MgUser -All
Get-MgGroup -All
Get-MgDevice -All

# Create operations
New-MgUser -DisplayName "Jane Smith" -UserPrincipalName "[email protected]" ...
New-MgGroup -DisplayName "New Group" -MailEnabled $false -SecurityEnabled $true ...

# Update operations
Update-MgUser -UserId user@yourdomain.com -Department "Engineering"
Update-MgGroup -GroupId <GroupId> -Description "Updated description"

# Delete operations
Remove-MgUser -UserId user@yourdomain.com
Remove-MgGroup -GroupId <GroupId>

# Direct API call for operations without a dedicated cmdlet
Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/me"

Finding the right permissions

Every Graph operation requires specific permission scopes. Request only the permissions your script actually needs.
# Find cmdlets and their required permissions
Find-MgGraphCommand -Command Get-MgUser | Select-Object -ExpandProperty Permissions

# Find the command for a given API endpoint
Find-MgGraphCommand -Uri "/users" -Method GET
PermissionTypePurpose
User.ReadDelegatedRead the signed-in user’s profile
User.Read.AllDelegated / ApplicationRead all user profiles
User.ReadWrite.AllDelegated / ApplicationCreate, update, and delete users
Directory.Read.AllDelegated / ApplicationRead all directory objects
Connect-MgGraph -Scopes "User.Read.All"
PermissionTypePurpose
Group.Read.AllDelegated / ApplicationRead all groups
Group.ReadWrite.AllDelegated / ApplicationCreate, update, and delete groups
GroupMember.ReadWrite.AllDelegated / ApplicationManage group membership
Connect-MgGraph -Scopes "Group.ReadWrite.All", "GroupMember.ReadWrite.All"
PermissionTypePurpose
Mail.ReadDelegated / ApplicationRead mail in all mailboxes
Mail.ReadWriteDelegated / ApplicationRead and write mail in all mailboxes
Mail.SendDelegated / ApplicationSend mail as any user
Calendars.ReadDelegated / ApplicationRead calendars in all mailboxes
Connect-MgGraph -Scopes "Mail.Read", "Mail.Send"
PermissionTypePurpose
Sites.Read.AllDelegated / ApplicationRead all SharePoint sites
Sites.ReadWrite.AllDelegated / ApplicationRead and write all SharePoint sites
Team.ReadBasic.AllDelegated / ApplicationList all teams
TeamMember.ReadWrite.AllDelegated / ApplicationManage team membership
Channel.ReadBasic.AllDelegated / ApplicationList channels in all teams
Connect-MgGraph -Scopes "Sites.Read.All", "Team.ReadBasic.All"
PermissionTypePurpose
Policy.Read.AllDelegated / ApplicationRead all policies including CA policies
Policy.ReadWrite.ConditionalAccessDelegated / ApplicationCreate and modify CA policies
AuditLog.Read.AllDelegated / ApplicationRead audit log data
IdentityRiskEvent.Read.AllDelegated / ApplicationRead risk detection events
Connect-MgGraph -Scopes "Policy.Read.All", "AuditLog.Read.All"

Pagination and large result sets

Graph API responses are paginated. The -All switch in Graph cmdlets handles pagination automatically.
# Use -All to retrieve all pages automatically
$allUsers = Get-MgUser -All

# For direct API calls, handle pagination manually
$uri = "https://graph.microsoft.com/v1.0/users"
$users = @()

do {
    $response = Invoke-MgGraphRequest -Method GET -Uri $uri
    $users += $response.value
    $uri = $response.'@odata.nextLink'
} while ($uri)

Write-Host "Total users: $($users.Count)"
Avoid using -All against very large tenants without filtering first. Retrieving tens of thousands of objects without a -Filter parameter can be slow and may hit throttling limits. Use -Filter to narrow results where possible.

Build docs developers (and LLMs) love