Clean Up M365 With PowerShell and MSGraph

Managing Microsoft 365 (M365) accounts can be a bit of a pain, especially when it comes to cleaning up inactive or unnecessary accounts. Fortunately, the Microsoft.Graph PowerShell modules give us some powerful tools to automate and streamline this process. Today, we’ll have a quick look at how to clean up M365 accounts, along with a few tips and tricks. Let’s get into it!

Prerequisites

Before we dive into the juicy bits, we need to cover some prerequisites:

1. Microsoft Graph PowerShell SDK: Obviously to use the Microsoft Graph PowerShell module, you’ll need to install it using the following command:

PowerShell
Install-PSResource -name Microsoft.Graph

2.Administrator Role: Next you will need to have either the global administrator or user administrator role in your M365 tenant.

3. Graph API Permissions: Ensure you have the `User.ReadWrite.All` Graph API permission. More on this in a bit.

Connecting to Microsoft Graph

Before we go too much deeper, we should briefly talk about “Scopes” and authentication in the Graph PowerShell SDK. I say briefly because it would take a much longer post (or series of posts) to fully delve into the topics of scopes and authentications. But what is a “scope”? You can think about a scope as a group of permissions. The names are pretty self-explanatory.

For example, the scope we will use today is “User.ReadWrite.All“, but if you were just searching for users with no intention of changing or writing to a user record, you could use “User.Read.All“. The best practice is to only use the level of permission that you actually need at that time. The number of scopes is constantly changing as Graph workloads are added and deprecated over time. As of this writing there are over 500 unique scopes NOT counting Beta scopes! The official list is here, and a community-maintained list is here.

Thankfully there are only two types of authentications – delegated or application. The easy way to think about it is this – use ‘delegated’ for interactive work and ‘application’ for automation work. The full explanation of authentications is here.

Got it? good! Now, authenticate and connect to your Microsoft Graph environment by running the following command:

PowerShell
Connect-MgGraph -Scopes "User.ReadWrite.All"

This will pop up a graphical login screen complete with MFA and all the normal “Logging into Microsoft/Azure/Entra” goodies.

Now that you are connected, we can get to work! Before we start slashing and burning through user accounts, let’s start with a bit of a search, shall we?

Searching for a Single User

Search for a user with the Get-MgUser cmdlet like this:

PowerShell
$UserName = "john.doe@contoso.com"
Get-MgUser -Filter "userPrincipalName eq '$UserName'"

Pretty simple huh? Now to build on that, we’ll use the same search basics to find and remove users to clean up your M365 tenant.

Removing a Single User

To remove a single user from your M365 tenant, use the Remove-MgUser cmdlet. For example:

PowerShell
$UserName = "john.doe@contoso.com"
$UserId = (Get-MgUser -Filter "userPrincipalName eq '$UserName'").Id
Remove-MgUser -UserId $UserId -Confirm:$false

Removing Multiple Users

You can remove multiple users by iterating through a list of user IDs, like this:

PowerShell
$userIds = @("user1@contoso.com", "user2@contoso.com", "user3@contoso.com")
foreach ($userId in $userIds) {
    Remove-MgUser -UserId $userId -Confirm:$false
}

Removing Users from a CSV File

Or, if you have a list of users in a CSV file, you can remove them using the following script:

PowerShell
$csvPath = "C:\Path\To\Users.csv"
$users = Import-Csv -Path $csvPath
foreach ($user in $users) {
    Remove-MgUser -UserId $user.UserPrincipalName -Confirm:$false
}

Error Handling and Best Practices

Always, when working with PowerShell automation it’s important to implement error handling. Here are some of the errors you may encounter and some solutions:

Error: 404 Not Found

Cause: The specified user ID does not exist in the tenant.
Solution: Verify the User information (spelling etc.).

Error: 403 Forbidden

Cause: Insufficient permissions to delete the user.
Solution: Check your account has the necessary M365 admin permissions (e.g., User Administrator or Global Administrator) and Graph API permissions (User.ReadWrite.All).

Error: 400 Bad Request

Cause: The URI or method is incorrectly formatted. This is basically a syntax error.
Solution: Double-check your commands and make certain the -filter you are using is on a property that accepts the filter.

This is ‘Just the Beginning’

There is a TON of things you can do with the Graph SDK in PowerShell – be forewarned – it can be a deep rabbit hole to dive down. To get you started, I’ve put some links below to some official docs on the subject. Have fun and happy scripting!

Microsoft Graph PowerShell documentation
PowerShell.org: Microsoft Graph PowerShell Module: Getting Started Guide

Leave a Reply

Scroll to Top