The Problem: Your AzureAD Scripts Are Broken
If you have been managing Microsoft 365 and Azure environments with PowerShell for any length of time, you almost certainly have scripts built on AzureAD or MSOnline cmdlets. Those scripts are now broken, or will be soon. Microsoft officially retired both modules, with MSOnline going dark in mid-2025 and the AzureAD module following shortly after. Scripts that once ran flawlessly will now throw errors, fail silently, or simply stop working, leaving user provisioning pipelines, reporting jobs, and automation workflows in an unreliable state.
The good news is that the replacement, Microsoft Entra PowerShell, is mature, well-documented, and even offers a compatibility alias layer that can get your existing scripts working again with minimal changes. This guide walks you through the migration step by step, with before-and-after code examples for the most common admin tasks.
Prerequisites
- PowerShell 7.2 or later (recommended; PowerShell 5.1 is supported but limited)
- An Entra ID account with at least User Administrator or Global Reader role for most read operations
- Ability to install PowerShell modules (local admin or user-scope install)
- Existing scripts using
Connect-AzureAD,Get-AzureADUser,Set-MsolUser, or similar cmdlets
Step 1: Install Microsoft Entra PowerShell
The new module is published to the PowerShell Gallery under the name Microsoft.Entra. Install it alongside the beta sub-module, which contains preview cmdlets including the new Agent Identity features introduced in v1.2.0.
# Install the stable module (user scope if you lack admin rights)
Install-Module Microsoft.Entra -Scope CurrentUser -Force
# Optionally install the beta module for preview features
Install-Module Microsoft.Entra.Beta -Scope CurrentUser -Force
# Verify the installed version
Get-Module Microsoft.Entra -ListAvailable | Select-Object Name, Version
Once installed, connect to your tenant. The authentication experience uses the modern MSAL stack and supports MFA, device code flow, and certificate-based auth out of the box.
# Interactive login (prompts browser-based MFA if required)
Connect-Entra -Scopes "User.Read.All", "Group.ReadWrite.All", "Directory.Read.All"
# Non-interactive login using a service principal with certificate
Connect-Entra -TenantId "your-tenant-id" `
-ClientId "your-app-id" `
-CertificateThumbprint "ABC123..."
Step 2: Use the Compatibility Alias Layer (Quick Fix)
If you have a large library of AzureAD scripts and need them working immediately, Microsoft Entra PowerShell ships with a built-in alias layer. Enabling it maps the old *-AzureAD* cmdlet names to their Entra equivalents, so your existing scripts run without modification.
# Enable AzureAD aliases, run this after Connect-Entra
Enable-EntraAzureADAlias
# Your old scripts can now call AzureAD cmdlets transparently
Get-AzureADUser -Filter "DisplayName eq 'Kim Heineborn'"
This is a useful bridge, but treat it as temporary. The aliases add overhead and do not cover 100% of edge cases. Schedule time to migrate scripts to native Entra cmdlets as covered below.
Step 3: Migrate Common Admin Tasks
The naming convention is consistent across the new module: *-AzureAD* becomes *-Entra*. Here is a practical before-and-after example covering user management, group membership, and account management, three of the most common automation scenarios.
# BEFORE (AzureAD module, now retired)
# Get all licensed users
$licensedUsers = Get-AzureADUser -All $true | Where-Object { $_.AssignedLicenses }
# Add a user to a group
Add-AzureADGroupMember -ObjectId $groupId -RefObjectId $userId
# Disable a user account
Set-AzureADUser -ObjectId $userId -AccountEnabled $false
# AFTER (Microsoft Entra PowerShell)
# Get all licensed users
$licensedUsers = Get-EntraUser -All | Where-Object { $_.AssignedLicenses }
# Add a user to a group
Add-EntraGroupMember -GroupId $groupId -MemberId $userId
# Disable a user account
Set-EntraUser -UserId $userId -AccountEnabled $false
Step 4: Automate Offboarding with Entra PowerShell
A real-world example that combines several cmdlets: a complete user offboarding function that disables the account, removes all group memberships, and revokes active sessions. This replaces a common pattern that previously relied on the AzureAD module.
function Invoke-EntraUserOffboard {
param(
[Parameter(Mandatory)]
[string]$UserPrincipalName
)
$user = Get-EntraUser -UserId $UserPrincipalName
if (-not $user) {
Write-Warning "User '$UserPrincipalName' not found."
return
}
Write-Host "Offboarding $($user.DisplayName)..." -ForegroundColor Cyan
# 1. Disable the account
Set-EntraUser -UserId $user.Id -AccountEnabled $false
Write-Host " [OK] Account disabled"
# 2. Revoke all refresh tokens (force sign-out everywhere)
Revoke-EntraUserAllRefreshToken -UserId $user.Id
Write-Host " [OK] All sessions revoked"
# 3. Remove from all Entra groups
$memberships = Get-EntraUserMembership -UserId $user.Id |
Where-Object { $_.OdataType -eq '#microsoft.graph.group' }
foreach ($group in $memberships) {
try {
Remove-EntraGroupMember -GroupId $group.Id -MemberId $user.Id
Write-Host " [OK] Removed from group: $($group.DisplayName)"
} catch {
Write-Warning " Could not remove from $($group.DisplayName): $_"
}
}
Write-Host "Offboarding complete for $UserPrincipalName." -ForegroundColor Green
}
# Usage
Connect-Entra -Scopes "User.ReadWrite.All", "Group.ReadWrite.All"
Invoke-EntraUserOffboard -UserPrincipalName "[email protected]"
Step 5: Audit Stale Guest Accounts
Another common automation task is identifying guest accounts that have not signed in recently. The Entra PowerShell equivalent uses the same Graph-backed properties, now surfaced cleanly through the -Property parameter.
# Report on guest users who have not signed in for 90 or more days
$cutoffDate = (Get-Date).AddDays(-90)
$staleGuests = Get-EntraUser -All -Filter "UserType eq 'Guest'" `
-Property DisplayName, UserPrincipalName, SignInActivity, CreatedDateTime |
Where-Object {
$lastSignIn = $_.SignInActivity.LastSignInDateTime
-not $lastSignIn -or [datetime]$lastSignIn -lt $cutoffDate
} |
Select-Object DisplayName, UserPrincipalName,
@{N='LastSignIn'; E={ $_.SignInActivity.LastSignInDateTime ?? 'Never' }},
CreatedDateTime
# Export to CSV for review
$staleGuests | Export-Csv -Path ".\StaleGuests_$(Get-Date -Format yyyyMMdd).csv" -NoTypeInformation
Write-Host "Found $($staleGuests.Count) stale guest accounts. Report saved."
Putting It All Together
Migrating away from the retired AzureAD and MSOnline modules does not have to be a painful big-bang project. A practical approach is to use the compatibility alias layer as an immediate safety net, then systematically replace cmdlets in your highest-priority scripts first, typically those used in automated pipelines like user provisioning, offboarding, and license reporting.
The Microsoft Entra PowerShell v1.2.0 release makes this easier than ever, with near-complete coverage of AzureAD cmdlets, consistent naming conventions, and first-class support for modern authentication flows. The module is actively developed, well-maintained, and, unlike the retired modules, fully aligned with the Microsoft Graph API, meaning it will continue to receive new capabilities as Entra ID evolves.
Start by auditing your existing scripts with Get-Command -Module AzureAD to inventory what you are using, prioritise by risk and frequency, and work through the migration using the patterns shown in this guide. Your automation will be more resilient, and you will be well positioned for whatever comes next in the Entra ecosystem.