Anyone who has managed identities in Microsoft 365 over the last few years has used the MSOnline and AzureAD PowerShell modules almost every day. User overviews, bulk licensing, onboarding workflows and scheduled task automations have depended on them for a long time. On March 30, 2024, both modules were officially deprecated, and Microsoft clearly recommends moving to the Microsoft Graph PowerShell SDK (or to Microsoft Entra PowerShell, which was still in preview at that point).
A practical inventory shows where the old modules still run
In most of the tenants I support, MSOnline and AzureAD cmdlets are still buried in onboarding scripts, reporting jobs and scheduled automation. If you want to avoid surprises later, you have to track these dependencies down first. I usually begin by searching script folders and repositories for the classic commands Connect-MsolService and Connect-AzureAD. The more useful check, though, is the Entra sign-in log. In the Microsoft Entra admin center, under Monitoring → Sign-in logs, you can filter by the application "Azure Active Directory PowerShell". That quickly reveals scheduled or unattended jobs that still use the old modules, even when they run under service accounts or on machines nobody has thought about in years.
flowchart TD
Scripts["Search scripts"] --> Cmdlets["Find MSOnline/AzureAD cmdlets"]
Cmdlets --> SignIns["Check Entra sign-in logs"]
SignIns --> Tasks["Identify scheduled tasks"]
Tasks --> Migration["Migrate to Graph PowerShell"]
Figure: The usual sequence for finding MSOnline and AzureAD script usage and migrating it.
Older tenants in particular tend to have dozens of production scripts that depend on these modules, and each one has to be updated.
Most MSOnline and AzureAD cmdlets map to a Graph equivalent
Microsoft's migration guidance leaves no room for doubt: new automation should use the Microsoft Graph PowerShell SDK. For day-to-day work, that means replacing familiar cmdlets like Get-MsolUser and Set-AzureADUser with Get-MgUser and Update-MgUser. Microsoft publishes a table that maps old cmdlets to new ones. The Graph cmdlets cover the old use cases in most cases, but the syntax and some of the concepts are different. Licensing is a good example. It now runs through Set-MgUserLicense, and if you've used the old modules for years, that takes a while to get used to.
This is what a typical licence assignment looks like in Graph PowerShell:
# Prerequisites: PowerShell 7, Microsoft.Graph module installed, User Administrator role or higher
Connect-MgGraph -Scopes User.ReadWrite.All
$user = Get-MgUser -UserId "[email protected]"
Set-MgUserLicense -UserId $user.Id -AddLicenses @{SkuId = "{licence-guid}"} -RemoveLicenses @()
Practical tip: A lot of scripts used MSOnline's
Get-MsolUserfor licensing simply because it was so easy. Moving to Graph keeps your automation working in the future, and you also get better filtering and export options. With the Graph authentication commands you can protect scripts with certificate-based app-only authentication instead of putting credentials in them.
Certificate-based app-only authentication replaces stored credentials
Scheduled tasks and unattended automation can't use interactive sign-in. The Graph PowerShell SDK supports app-only authentication with certificates, which is a big step up from the old modules. You register an app in Entra ID, assign the application permissions it needs (for example User.ReadWrite.All for user administration), upload your certificate and then call Connect-MgGraph with the app ID in your scripts. Your automation then no longer depends on local credential caches or plain text passwords.
Real migrations run into the same few problems
Moving away from MSOnline and AzureAD PowerShell is more than search and replace. In real tenants I keep running into the same issues:
- Old scripts are often monolithic and full of hardcoded values, so you end up rewriting them rather than adjusting a few lines.
- The Graph SDK is stricter about permissions, particularly in app-only scenarios.
- The "Microsoft.Graph" module isn't always available in automation environments such as Azure Automation or on older servers.
Once a script is migrated, I always go back to the Entra admin center (Monitoring → Sign-in logs) to make sure the scheduled tasks authenticate the way they should and don't hit permission errors. Working through this methodically now spares you a lot of frustration later, because the deprecated modules no longer get updates or support.
I recommend planning the migration now instead of waiting
The retirement of MSOnline and AzureAD PowerShell has only been announced so far, but you don't want to wait until something breaks in production. Moving to Graph is more than a change of syntax. You have to adopt new authentication patterns and get to know a different permission model. Inventory the affected scripts and automations first, then work with the migration maps, test properly and document what you change. In my experience that effort pays off far better than hurried fixes at the last minute. If you're looking for more modernization topics, such as Conditional Access or cleaning up guest accounts, take a look at my posts on getting started with Conditional Access in Entra ID and cleaning up guest accounts with access reviews.


