Skip to content

Instantly share code, notes, and snippets.

@timothywarner
Created April 2, 2025 18:46
Show Gist options
  • Save timothywarner/823c1a756ba0d66a98f248e2d924697f to your computer and use it in GitHub Desktop.
Save timothywarner/823c1a756ba0d66a98f248e2d924697f to your computer and use it in GitHub Desktop.
Get comfortable working with the Microsoft Graph API by using PowerShell
# πŸ”Œ Connect-MgGraph: The Ultimate Practice Guide
[![PowerShell 7.2+](https://img.shields.io/badge/PowerShell-7.2+-blue.svg)](https://github.com/PowerShell/PowerShell)
[![Microsoft Graph](https://img.shields.io/badge/Microsoft%20Graph-SDK-green.svg)](https://github.com/microsoftgraph/msgraph-sdk-powershell)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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