Identify/Disable Inactive M365 Users Using Graph PowerShell

Managing inactive user accounts is crucial for ensuring the security and efficiency of your Microsoft 365 environment. Over time, some users may stop using their accounts, leaving them vulnerable to unauthorized access or unnecessarily consuming licenses. A best practice is to periodically review and disable inactive accounts to protect company data and optimize resource usage.

In this article, we provide a PowerShell script that connects to Microsoft Graph to retrieve inactive users based on their last sign-in activity and automatically disables their accounts. This approach helps administrators maintain a secure environment by ensuring that inactive accounts are handled appropriately.

The Script:


    # Connect to Microsoft Graph with the necessary scopes
    Connect-MgGraph -Scopes "User.ReadWrite.All", "AuditLog.Read.All"

    # Set the threshold for inactivity (e.g., users inactive for 90 days)
    $inactivityThresholdDays = 90
    $cutoffDate = (Get-Date).AddDays(-$inactivityThresholdDays).ToString("yyyy-MM-dd")

    # Retrieve all users and their last sign-in activity
    $inactiveUsers = Get-MgUser -All -Property Id, DisplayName, UserPrincipalName, SignInActivity | Where-Object {
    $_.SignInActivity.LastSignInDateTime -lt $cutoffDate
    }

    # Check if there are inactive users
    if ($inactiveUsers) {
        # Create an empty array to store the results
        $results = @()

        Write-Host "Disabling users inactive for more than $inactivityThresholdDays days..."

        # Loop through each inactive user
        foreach ($user in $inactiveUsers) {
            # Disable the user account using -BodyParameter
            $disableParams = @{
            "AccountEnabled" = $false
            }
        Update-MgUser -UserId $user.UserPrincipalName -BodyParameter $disableParams

        # Add the user details to the results array
        $results += [pscustomobject]@{
        "ID"             = $user.Id
        "Name"           = $user.DisplayName
        "UPN"            = $user.UserPrincipalName
        "Last Sign-In"   = $user.SignInActivity.LastSignInDateTime
        "Account Status" = "Disabled"
        }
    }

    # Output the results in a tabular format
    $results | Format-Table -AutoSize
    } else {
    Write-Host "No inactive users found in the last $inactivityThresholdDays days."
    }

    # Disconnect session
    Disconnect-MgGraph

How the Script Works

This PowerShell script utilizes the Microsoft Graph PowerShell module to identify and disable inactive Microsoft 365 users. Here’s how each part of the script functions:

  • Connect to Microsoft Graph: The script starts by connecting to Microsoft Graph using the necessary permissions (User.ReadWrite.All and AuditLog.Read.All). These permissions allow the script to retrieve user details and their last sign-in activity, as well as update account status.
  • Set Inactivity Threshold: You can define the number of days of inactivity by setting the $inactivityThresholdDays variable. For example, setting it to 90 means the script will identify users who haven’t signed in for the past 90 days.
  • Retrieve User Data: The script uses the Get-MgUser cmdlet to retrieve user information, including their last sign-in activity. Users who have been inactive beyond the cutoff date (calculated based on the threshold) are filtered for further action.
  • Disable Inactive Users: For each inactive user, the script disables their account by setting the AccountEnabled property to $false using the -BodyParameter option. This ensures that users cannot access Microsoft 365 services, but their data remains intact for future needs.
  • Output Results: The script stores the user details (ID, DisplayName, UserPrincipalName, Last Sign-In Date, and Account Status) in an array and then outputs the results in a clean tabular format using Format-Table.

Further Enhancements

There are several ways to further enhance this script based on your administrative needs:

  • Export Results to CSV: For reporting purposes, the results of the script can be exported to a CSV file:
  • 
        $results | Export-Csv -Path "C:\InactiveUsers.csv" -NoTypeInformation
    
  • Email Notifications: You can notify users of their inactivity before disabling their accounts. An email notification could be added to the script using PowerShell’s Send-MailMessage cmdlet. This would give users a chance to reactivate their accounts if needed:
  • Send-MailMessage -To $user.UserPrincipalName -Subject "Your Account is Inactive" -Body "Your Microsoft 365 account will be disabled due to inactivity." -SmtpServer "smtp.yourserver.com"
  • Reassign Licenses: To optimize license usage, you could modify the script to automatically unassign licenses from inactive users after disabling their accounts:
  • Set-MgUserLicense -UserId $user.Id -RemoveLicenses @{SkuId = $licenseSkuId}
  • Bulk Operations for Large Organizations: If your organization has thousands of users, running the script in batches can improve performance. You can retrieve users in chunks to avoid overloading the system or encountering timeout issues.

Possible Errors & Solutions

  • Error: No users found with SignInActivity property
    • Cause: In some environments, sign-in activity might not be logged for certain users (e.g., service accounts or newly created users).
    • Solution: Exclude these accounts by adding an additional filter to the script or manually check these accounts for any recent activity through audit logs.
  • Error: Update-MgUser : Insufficient privileges
    • Cause: The script requires the User.ReadWrite.All permission to disable accounts.
    • Solution: Ensure that the required permission is granted to your Microsoft Graph app or your PowerShell session when connecting to Microsoft Graph`.
  • Error: Unable to retrieve SignInActivity
    • Cause: Sometimes, the SignInActivity property may not be populated for certain users due to system delays or logging configurations.
    • Solution: Try running the script at a later time or adjust your logging settings in Azure AD.

Conclusion

This PowerShell script provides a powerful and automated way to manage inactive users in your Microsoft 365 environment. By identifying users who haven’t signed in for a set period and disabling their accounts, you can enhance security and free up licenses. The script’s flexible design allows for further enhancements, such as exporting results, sending notifications, or automating license reassignment.

Regularly running this script can help administrators ensure that their environment is clean and secure by preventing inactive accounts from becoming potential security risks. Let me know if you’d like to explore more improvements or automation options for your user management process!

Suggested Reading

© m365corner.com. All Rights Reserved. Design by HTML Codex