Created
April 2, 2025 18:46
-
-
Save timothywarner/823c1a756ba0d66a98f248e2d924697f to your computer and use it in GitHub Desktop.
Get comfortable working with the Microsoft Graph API by using PowerShell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# π Connect-MgGraph: The Ultimate Practice Guide | |
[](https://github.com/PowerShell/PowerShell) | |
[](https://github.com/microsoftgraph/msgraph-sdk-powershell) | |
[](https://opensource.org/licenses/MIT) | |
> A comprehensive guide to mastering the Connect-MgGraph cmdlet for Microsoft 365 and Azure administrators | |
## π Table of Contents | |
- [Introduction](#introduction) | |
- [Module Installation](#module-installation) | |
- [Migration from Legacy Modules](#migration-from-legacy-modules) | |
- [Basic Connection](#basic-connection) | |
- [Authentication Methods](#authentication-methods) | |
- [Managing Scopes](#managing-scopes) | |
- [Tenant Selection](#tenant-selection) | |
- [Connection Profiles](#connection-profiles) | |
- [Troubleshooting](#troubleshooting) | |
- [Common Scenarios](#common-scenarios) | |
- [Practical Examples](#practical-examples) | |
- [Additional Resources](#additional-resources) | |
## π Introduction | |
The Microsoft Graph PowerShell SDK provides a modern way to interact with Microsoft 365, Azure, and other Microsoft cloud services. At the heart of this SDK is the `Connect-MgGraph` cmdlet, which establishes authenticated connections to Microsoft Graph. | |
This guide provides practical examples and best practices for IT administrators and PowerShell enthusiasts working with Microsoft Graph. | |
## π¦ Module Installation | |
### Installing the Microsoft Graph PowerShell SDK | |
```powershell | |
# Check if the Microsoft Graph module is already installed | |
if (-not (Get-Module -ListAvailable -Name Microsoft.Graph)) { | |
# Install the Microsoft Graph PowerShell module | |
Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force | |
} | |
# Verify the installation | |
Get-Module -Name Microsoft.Graph -ListAvailable | Select-Object Name, Version | |
``` | |
### Installing Specific Microsoft Graph Module Components | |
```powershell | |
# Install only specific Microsoft Graph modules you need | |
Install-Module -Name Microsoft.Graph.Authentication -Scope CurrentUser -Force | |
Install-Module -Name Microsoft.Graph.Users -Scope CurrentUser -Force | |
Install-Module -Name Microsoft.Graph.Groups -Scope CurrentUser -Force | |
``` | |
## π Migration from Legacy Modules | |
### Transitioning from AzureAD and MSOnline Modules | |
```powershell | |
# Legacy way with AzureAD module | |
# Connect-AzureAD | |
# Legacy way with MSOnline module | |
# Connect-MsolService | |
# Modern approach with Microsoft Graph | |
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All" | |
# Mapping of common commands | |
# Old: Get-AzureADUser | |
# New: Get-MgUser | |
# Old: Get-MsolUser | |
# New: Get-MgUser | |
# Old: Get-AzureADGroup | |
# New: Get-MgGroup | |
``` | |
### Command Mapping Reference | |
<# | |
.SYNOPSIS | |
Essential command mapping between legacy modules and Microsoft Graph PowerShell SDK | |
#> | |
| Legacy Command | Microsoft Graph Command | Description | | |
|:---------------|:------------------------|:------------| | |
| `Connect-AzureAD`/`Connect-MsolService` | `Connect-MgGraph` | Establish connection | | |
| `Get-AzureADUser`/`Get-MsolUser` | `Get-MgUser` | Retrieve users | | |
| `Get-AzureADGroup`/`Get-MsolGroup` | `Get-MgGroup` | Retrieve groups | | |
| `New-AzureADUser`/`New-MsolUser` | `New-MgUser` | Create a new user | | |
| `Set-AzureADUser`/`Set-MsolUser` | `Update-MgUser` | Update user properties | | |
| `Remove-AzureADUser`/`Remove-MsolUser` | `Remove-MgUser` | Delete a user | | |
| `Get-AzureADUserMembership` | `Get-MgUserMemberOf` | Get user's group memberships | | |
| `Add-AzureADGroupMember` | `New-MgGroupMember` | Add member to group | | |
| `Get-AzureADGroupMember` | `Get-MgGroupMember` | Get group members | | |
| `Get-AzureADDirectoryRole`/`Get-MsolRole` | `Get-MgDirectoryRole` | Get directory roles | | |
## π Basic Connection | |
### Simple Connection with Default Settings | |
```powershell | |
# Connect with default settings (interactive browser sign-in) | |
Connect-MgGraph | |
# Check connection status | |
Get-MgContext | |
``` | |
### Connecting with Specific Scopes | |
```powershell | |
# Connect with specific permissions | |
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All", "Directory.Read.All" | |
``` | |
## π Authentication Methods | |
### Interactive Browser Authentication | |
```powershell | |
# Default method - opens a browser for authentication | |
Connect-MgGraph -Scopes "User.Read.All" | |
``` | |
### Device Code Authentication | |
```powershell | |
# Useful for remote sessions without a browser | |
Connect-MgGraph -UseDeviceCode -Scopes "User.Read.All" | |
``` | |
### Certificate-Based Authentication | |
```powershell | |
# Using a certificate for authentication (common in automation) | |
Connect-MgGraph -ClientId "YOUR_APP_ID" -TenantId "YOUR_TENANT_ID" -CertificateName "CN=CertName" -Scopes "User.Read.All" | |
# Alternative using certificate thumbprint | |
Connect-MgGraph -ClientId "YOUR_APP_ID" -TenantId "YOUR_TENANT_ID" -CertificateThumbprint "CERTIFICATE_THUMBPRINT" -Scopes "User.Read.All" | |
``` | |
### Client Secret Authentication | |
```powershell | |
# Store your application ID and tenant ID | |
$ApplicationId = "YOUR_APP_ID" | |
$TenantId = "YOUR_TENANT_ID" | |
# More secure method to handle credentials | |
$ClientSecretCredential = Get-Credential -Message "Enter the client secret" -UserName $ApplicationId | |
# Alternative when automation is required: | |
# $SecuredPassword = ConvertTo-SecureString -String "YOUR_CLIENT_SECRET" -AsPlainText -Force | |
# $ClientSecretCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $SecuredPassword | |
# Connect using client secret (app-only authentication) | |
Connect-MgGraph -TenantId $TenantId -ClientSecretCredential $ClientSecretCredential | |
``` | |
### Managed Identity Authentication (Azure) | |
```powershell | |
# For scripts running in Azure with managed identity | |
Connect-MgGraph -Identity | |
``` | |
## π Managing Scopes | |
### Understanding Permission Scopes | |
```powershell | |
# List commonly used scopes | |
$commonScopes = @( | |
"User.Read.All", # Read all users' full profiles | |
"Group.Read.All", # Read all groups | |
"Directory.Read.All", # Read directory data | |
"Directory.ReadWrite.All", # Read and write directory data | |
"User.ReadWrite.All", # Read and write all users' full profiles | |
"Group.ReadWrite.All" # Read and write all groups | |
) | |
# Display scopes with descriptions | |
$commonScopes | ForEach-Object { | |
[PSCustomObject]@{ | |
Scope = $_ | |
Description = switch ($_) { | |
"User.Read.All" { "Read all users' full profiles" } | |
"Group.Read.All" { "Read all groups" } | |
"Directory.Read.All" { "Read directory data" } | |
"Directory.ReadWrite.All" { "Read and write directory data" } | |
"User.ReadWrite.All" { "Read and write all users' full profiles" } | |
"Group.ReadWrite.All" { "Read and write all groups" } | |
} | |
} | |
} | |
``` | |
### Adding Scopes to Existing Connection | |
```powershell | |
# First connection with limited scope | |
Connect-MgGraph -Scopes "User.Read" | |
# Add more scopes later (requires re-authentication) | |
Connect-MgGraph -Scopes "User.Read", "Group.Read.All" -ForceRefresh | |
``` | |
## π’ Tenant Selection | |
### Connecting to a Specific Tenant | |
```powershell | |
# Connect to a specific tenant by ID | |
Connect-MgGraph -TenantId "YOUR_TENANT_ID" -Scopes "User.Read.All" | |
# Connect using tenant domain name | |
Connect-MgGraph -TenantId "contoso.onmicrosoft.com" -Scopes "User.Read.All" | |
``` | |
### Working with Multiple Tenants | |
```powershell | |
# Connect to first tenant | |
Connect-MgGraph -TenantId "tenant1.onmicrosoft.com" -Scopes "User.Read.All" | |
$tenant1Users = Get-MgUser -Top 10 | |
# Disconnect and connect to second tenant | |
Disconnect-MgGraph | |
Connect-MgGraph -TenantId "tenant2.onmicrosoft.com" -Scopes "User.Read.All" | |
$tenant2Users = Get-MgUser -Top 10 | |
``` | |
## π Connection Profiles | |
### Saving Connection Profiles | |
```powershell | |
# Create and save a connection profile | |
Select-MgProfile -Name "beta" | |
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All" | |
$connectionProfile = @{ | |
TenantId = (Get-MgContext).TenantId | |
Scopes = (Get-MgContext).Scopes | |
ProfileName = (Get-MgProfile).Name | |
} | |
$connectionProfile | ConvertTo-Json | Set-Content -Path "MgConnectionProfile.json" | |
``` | |
### Loading Connection Profiles | |
```powershell | |
# Load a saved connection profile | |
$savedProfile = Get-Content -Path "MgConnectionProfile.json" | ConvertFrom-Json | |
Select-MgProfile -Name $savedProfile.ProfileName | |
Connect-MgGraph -TenantId $savedProfile.TenantId -Scopes $savedProfile.Scopes | |
``` | |
## β οΈ Troubleshooting | |
### Common Connection Issues | |
```powershell | |
# Check if you're connected | |
if (-not (Get-MgContext)) { | |
Write-Warning "Not connected to Microsoft Graph. Attempting to connect..." | |
try { | |
Connect-MgGraph -Scopes "User.Read.All" | |
} | |
catch { | |
Write-Error "Failed to connect to Microsoft Graph: $_" | |
# Common issues: | |
# 1. Network connectivity problems | |
# 2. Invalid credentials | |
# 3. Insufficient permissions | |
# 4. MFA requirements | |
} | |
} | |
# Check current connection details | |
Get-MgContext | Format-List | |
# Verify installed Microsoft Graph modules | |
Get-Module -Name Microsoft.Graph* -ListAvailable | |
``` | |
### Handling Token Expiration | |
```powershell | |
# Function to ensure valid connection | |
function Ensure-MgConnection { | |
if (-not (Get-MgContext)) { | |
Write-Verbose "No active connection found. Connecting to Microsoft Graph..." | |
Connect-MgGraph -Scopes "User.Read.All" | |
return | |
} | |
try { | |
# Test connection by making a simple call | |
Get-MgUser -Top 1 -ErrorAction Stop | Out-Null | |
Write-Verbose "Connection is valid" | |
} | |
catch { | |
Write-Verbose "Connection expired. Reconnecting..." | |
Connect-MgGraph -Scopes (Get-MgContext).Scopes -ForceRefresh | |
} | |
} | |
# Usage | |
Ensure-MgConnection | |
``` | |
## π§© Common Scenarios | |
### User Management | |
```powershell | |
# Connect with appropriate scopes | |
Connect-MgGraph -Scopes "User.Read.All", "User.ReadWrite.All" | |
# Get all users | |
Get-MgUser -Top 10 | Select-Object DisplayName, UserPrincipalName, Id | |
# Get a specific user | |
Get-MgUser -UserId "[email protected]" | Format-List | |
# Create a new user | |
$passwordProfile = @{ | |
Password = "P@ssw0rd123!" | |
ForceChangePasswordNextSignIn = $true | |
} | |
$newUser = @{ | |
DisplayName = "John Doe" | |
UserPrincipalName = "[email protected]" | |
MailNickname = "johndoe" | |
AccountEnabled = $true | |
PasswordProfile = $passwordProfile | |
} | |
New-MgUser @newUser | |
# Update a user | |
Update-MgUser -UserId "[email protected]" -DisplayName "John A. Doe" | |
# Delete a user | |
Remove-MgUser -UserId "[email protected]" | |
``` | |
### Group Management | |
```powershell | |
# Connect with appropriate scopes | |
Connect-MgGraph -Scopes "Group.Read.All", "Group.ReadWrite.All" | |
# Get all groups | |
Get-MgGroup -Top 10 | Select-Object DisplayName, Id, Description | |
# Create a new group | |
$newGroup = @{ | |
DisplayName = "Marketing Team" | |
Description = "Marketing department team group" | |
MailEnabled = $false | |
MailNickname = "marketingteam" | |
SecurityEnabled = $true | |
GroupTypes = @() | |
} | |
New-MgGroup @newGroup | |
# Add a member to a group | |
$group = Get-MgGroup -Filter "DisplayName eq 'Marketing Team'" | |
$user = Get-MgUser -UserId "[email protected]" | |
New-MgGroupMember -GroupId $group.Id -DirectoryObjectId $user.Id | |
# Get group members | |
Get-MgGroupMember -GroupId $group.Id | ForEach-Object { | |
Get-MgDirectoryObject -DirectoryObjectId $_.Id | |
} | |
``` | |
## π¬ Practical Examples | |
### Reporting and Auditing | |
```powershell | |
# Connect with appropriate scopes | |
Connect-MgGraph -Scopes "User.Read.All", "AuditLog.Read.All" | |
# Get recently created users | |
$yesterday = (Get-Date).AddDays(-1).ToString("yyyy-MM-dd") | |
Get-MgUser -Filter "createdDateTime ge $yesterday" | | |
Select-Object DisplayName, UserPrincipalName, CreatedDateTime | |
# Export all licensed users to CSV | |
Get-MgUser -All | Where-Object { $_.AssignedLicenses.Count -gt 0 } | | |
Select-Object DisplayName, UserPrincipalName, JobTitle, Department | | |
Export-Csv -Path "LicensedUsers.csv" -NoTypeInformation | |
``` | |
### Security and Compliance | |
```powershell | |
# Connect with appropriate scopes | |
Connect-MgGraph -Scopes "User.Read.All", "Directory.Read.All" | |
# Find accounts with admin roles | |
Get-MgDirectoryRole | ForEach-Object { | |
$role = $_ | |
Get-MgDirectoryRoleMember -DirectoryRoleId $role.Id | ForEach-Object { | |
$member = Get-MgDirectoryObject -DirectoryObjectId $_.Id | |
[PSCustomObject]@{ | |
RoleName = $role.DisplayName | |
MemberName = $member.AdditionalProperties.displayName | |
MemberUPN = $member.AdditionalProperties.userPrincipalName | |
} | |
} | |
} | Format-Table -AutoSize | |
# Find users with no MFA | |
Connect-MgGraph -Scopes "UserAuthenticationMethod.Read.All" | |
$users = Get-MgUser -All | |
foreach ($user in $users) { | |
$authMethods = Get-MgUserAuthenticationMethod -UserId $user.Id | |
if ($authMethods.Count -le 1) { | |
[PSCustomObject]@{ | |
DisplayName = $user.DisplayName | |
UserPrincipalName = $user.UserPrincipalName | |
MFAEnabled = $false | |
} | |
} | |
} | |
``` | |
### Automation and Scripting | |
```powershell | |
# Function to connect with error handling | |
function Connect-ToMicrosoftGraph { | |
param ( | |
[string[]]$Scopes = @("User.Read.All"), | |
[string]$TenantId, | |
[switch]$UseDeviceCode | |
) | |
try { | |
$params = @{ | |
Scopes = $Scopes | |
} | |
if ($TenantId) { | |
$params.TenantId = $TenantId | |
} | |
if ($UseDeviceCode) { | |
$params.UseDeviceCode = $true | |
} | |
Connect-MgGraph @params | |
Write-Host "β Successfully connected to Microsoft Graph" -ForegroundColor Green | |
return $true | |
} | |
catch { | |
Write-Host "β Failed to connect to Microsoft Graph: $_" -ForegroundColor Red | |
return $false | |
} | |
} | |
# Usage in a script | |
if (Connect-ToMicrosoftGraph -Scopes "User.Read.All", "Group.Read.All") { | |
# Proceed with script | |
$users = Get-MgUser -Top 10 | |
$groups = Get-MgGroup -Top 10 | |
# Do something with the data | |
$users | Export-Csv -Path "Users.csv" -NoTypeInformation | |
$groups | Export-Csv -Path "Groups.csv" -NoTypeInformation | |
} | |
else { | |
Write-Host "Script execution stopped due to connection failure" -ForegroundColor Red | |
} | |
``` | |
## π Additional Resources | |
- [Microsoft Graph PowerShell SDK Documentation](https://docs.microsoft.com/en-us/powershell/microsoftgraph/overview) | |
- [Microsoft Graph API Reference](https://docs.microsoft.com/en-us/graph/api/overview) | |
- [Microsoft Graph Explorer](https://developer.microsoft.com/en-us/graph/graph-explorer) | |
- [Microsoft Graph SDK GitHub Repository](https://github.com/microsoftgraph/msgraph-sdk-powershell) | |
--- | |
## π’ Disconnecting from Microsoft Graph | |
Always remember to disconnect your session when finished: | |
```powershell | |
# Disconnect from Microsoft Graph | |
Disconnect-MgGraph | |
# Verify disconnection | |
if (-not (Get-MgContext)) { | |
Write-Host "Successfully disconnected from Microsoft Graph" -ForegroundColor Green | |
} | |
``` | |
--- | |
Created with β€οΈ by a PowerShell enthusiast for the Microsoft community |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment