Why Automate Microsoft 365 User Offboarding?
Offboarding users is often a highly manual, multi-step process involving license removal, password resets, and mailbox conversions. When handled manually, it leaves room for human error—which in the context of offboarding, can lead to severe security vulnerabilities or compliance violations.
By leveraging Microsoft Graph PowerShell, you can create a standardized offboarding script that guarantees compliance, ensures zero downtime for shared data, and can be executed automatically and consistently when HR initiates an employee departure process.
The Essential Steps of M365 Offboarding
A robust offboarding script should execute the following operations in a specific sequence to ensure data retention and security. In 2024 and beyond, the industry standard is to use the Microsoft Graph PowerShell SDK rather than the legacy MSOnline or AzureAD modules.
1. Block Sign-in
The immediate first step is to prevent the user from authenticating.
# Block the user from signing in
Update-MgUser -UserId $UserId -AccountEnabled $false
Write-Host "User sign-in blocked." -ForegroundColor Green
2. Reset Password (Defense in Depth)
Although the account is blocked, resetting the password adds an extra layer of protection to ensure existing credentials cannot be used even if the block is accidentally lifted.
# Reset the user password
$PasswordProfile = @{
Password = "A-Strong-Random-Password-123!"
ForceChangePasswordNextSignIn = $true
}
Update-MgUser -UserId $UserId -PasswordProfile $PasswordProfile
Write-Host "Password reset successfully." -ForegroundColor Green
3. Revoke Active Sessions
Blocking sign-in doesn’t terminate existing sessions immediately. You must invalidate refresh tokens and force re-authentication across Microsoft 365 services.
# Revoke all active sessions
Revoke-MgUserSignInSession -UserId $UserId
Write-Host "Active sessions revoked." -ForegroundColor Green
4. Convert Mailbox to Shared
To preserve the departed employee’s emails without consuming a paid license, convert their mailbox to a Shared Mailbox. Note: This requires the ExchangeOnlineManagement module.
# Convert to Shared Mailbox
Set-Mailbox -Identity $UserUPN -Type Shared
Write-Host "Mailbox converted to Shared." -ForegroundColor Green
5. Configure Email Forwarding (Optional)
Ensure that important business communications are not lost by forwarding the departed user’s emails to their manager.
# Set email forwarding to manager
Set-Mailbox -Identity $UserUPN -ForwardingSmtpAddress $ManagerEmail -DeliverToMailboxAndForward $true
Write-Host "Email forwarding enabled." -ForegroundColor Green
6. Transfer OneDrive Ownership
In an enterprise environment, an employee’s OneDrive files are often as critical as their mailbox. Ensure you grant the manager access to the departed employee’s OneDrive so data isn’t lost when the account is eventually purged.
# Grant manager Site Collection Admin rights to user's OneDrive
# Note: Requires PnP PowerShell and SharePoint Admin rights
Set-PnPTenantSite -Url $UserOneDriveUrl -Owners $ManagerEmail
Write-Host "OneDrive ownership transferred." -ForegroundColor Green
7. Strip Group Memberships
Remove the user from Microsoft 365 Groups and security groups to maintain a clean directory.
# Get only Group objects (filtering out Roles and Admin Units)
$Groups = Get-MgUserMemberOf -UserId $UserId -All | Where-Object { $_.'@odata.type' -eq '#microsoft.graph.group' }
foreach ($Group in $Groups) {
Remove-MgGroupMemberByRef -GroupId $Group.Id -DirectoryObjectId $UserId
}
Write-Host "Removed from all M365 and Security Groups." -ForegroundColor Green
8. Hide from Global Address List (GAL)
Hide the user from the organization’s address book so internal employees don’t try to contact them.
# Hide from GAL
Set-Mailbox -Identity $UserUPN -HiddenFromAddressListsEnabled $true
Write-Host "User hidden from GAL." -ForegroundColor Green
9. Remove Microsoft 365 Licenses
Before removing licenses, verify that mailbox retention, litigation hold, eDiscovery, and data retention policies are preserved. After mailbox conversion, licenses can typically be removed. However, shared mailboxes larger than 50 GB or using archive/compliance features may still require licensing.
# Get user licenses
$Licenses = Get-MgUserLicenseDetail -UserId $UserId
# Remove licenses
Set-MgUserLicense -UserId $UserId -RemoveLicenses $Licenses.SkuId -AddLicenses @()
Write-Host "Licenses removed successfully." -ForegroundColor Green
Best Practices for Offboarding Scripts
- Implement Logging: Always use
Start-Transcriptor custom logging functions to track exactly when and by whom offboarding tasks were performed. - Error Handling: Use
Try-Catchblocks in your scripts to ensure that if one step fails (e.g., a mailbox hasn’t provisioned yet), the script captures the error and alerts you rather than crashing silently. - Use a Dedicated Service Principal: When transitioning from manual scripts to automated workflows (like Azure Automation), use a dedicated service principal with application permissions (e.g.,
User.ReadWrite.All) rather than a personal admin account. - Retention and Compliance: Always align your offboarding scripts with your organization’s data retention policies to ensure legal and compliance holds are not broken during automated license removal.
👉 Explore SPClean to automatically find and strip permissions from orphaned users across your entire tenant.



