Retrieve M365 Disabled Users List Using Graph PowerShell

Tracking when a user account has been disabled in Azure Active Directory (Azure AD) is a vital part of managing user access and maintaining security. When a user’s sign-in is blocked, it’s crucial for administrators to have detailed records, including the time the action took place, the user who was disabled, the admin responsible, and whether the operation was successful. In this article, we will explore a PowerShell script that leverages Microsoft Graph to fetch audit logs and retrieve details of recently disabled users.

This guide will walk you through the script itself, how it works, ways to enhance it further, and common errors you may encounter along with their solutions.

The Script

# Import the Microsoft Graph PowerShell module
Import-Module Microsoft.Graph

# Authenticate and connect to Microsoft Graph
Connect-MgGraph -Scopes "AuditLog.Read.All"

# Define the date range for fetching disabled users (customize as needed)
$startDateTime = (Get-Date).AddDays(-30).ToString("yyyy-MM-ddTHH:mm:ssZ")  # Past 30 days

# Fetch all DirectoryAudit logs related to 'Update user' in the past 30 days
$allAuditLogs = Get-MgAuditLogDirectoryAudit -Filter "activityDisplayName eq 'Update user' and activityDateTime ge $startDateTime"

# Create an array to store the formatted results
$disabledUserDetails = @()

# Loop through the audit logs to process 'Update user' events
foreach ($event in $allAuditLogs) {
    $disabledTime = $event.ActivityDateTime
    $disabledUser = ($event.TargetResources | Where-Object { $_.UserPrincipalName }).UserPrincipalName
    $disabledBy = $event.InitiatedBy.User.UserPrincipalName
    $resultStatus = if ($event.Result -eq 'success') { 'Success' } else { 'Failed' }

    # Create an object for each record
    $userDetail = [pscustomobject]@{
        "Disabled Time"  = $disabledTime
        "Disabled User"  = $disabledUser
        "Disabled By"    = $disabledBy
        "Result Status"  = $resultStatus
    }

    # Add the object to the results array
    $disabledUserDetails += $userDetail
}

# Output the results in a tabular format
if ($disabledUserDetails.Count -eq 0) {
    Write-Host "No disabled user events found in the given date range."
} else {
    $disabledUserDetails | Format-Table -AutoSize

How This Script Works

This script makes use of Microsoft Graph’s audit logs to track when a user’s account is disabled. Here’s a step-by-step breakdown of how the script works:

  • Authentication: The script starts by connecting to Microsoft Graph using the Connect-MgGraph cmdlet with the AuditLog.Read.All permission, allowing the script to access audit logs that record administrative actions.
  • Setting the Date Range: The script defines a date range for fetching audit logs. By default, it checks logs for the past 30 days. You can customize this range to suit your needs.
  • Fetching Audit Logs: Using Get-MgAuditLogDirectoryAudit, the script retrieves audit logs related to user updates by filtering for entries where the ActivityDisplayName is 'Update user' and the action occurred within the specified date range.
  • Processing Audit Logs: The script loops through the audit logs, checking each log entry to extract key details. It identifies the time of the event (ActivityDateTime), the user who was disabled (UserPrincipalName), the admin who performed the action (InitiatedBy.UserPrincipalName), and the result status (Success or Failed).
  • Storing the Results: Each relevant event is stored in a custom PowerShell object with fields for the disabled time, user, admin, and result status.
  • Displaying the Results: The script outputs the results in a tabular format using Format-Table. If no events are found, the script displays a message indicating no disabled user events were found.

Further Enhancing the Script

The provided script is highly effective in tracking users whose sign-in has been disabled, but there are several ways to enhance it to make it more dynamic and useful in different scenarios::

  • Custom Date Input: Instead of a fixed date range, you can modify the script to allow user input for the start and end dates. This makes it more flexible for different reporting periods.
  • 
        $startDateTime = Read-Host "Enter start date (yyyy-MM-ddTHH:mm:ssZ)"
        $endDateTime = Read-Host "Enter end date (yyyy-MM-ddTHH:mm:ssZ)"
    
  • Export to CSV: To save the data for future reference or for sharing with other teams, the script can easily export the results to a CSV file.
  • $disabledUserDetails | Export-Csv -Path "DisabledUsersReport.csv" -NoTypeInformation
  • Automating Reports: You can schedule this script to run at regular intervals (e.g., weekly) using Task Scheduler or Azure Automation, sending reports to your email automatically:
  • Send-MailMessage -To "admin@example.com" -From "system@example.com" -Subject "Disabled Users Report" -Body "Please find the attached report." -Attachments "DisabledUsersReport.csv"
  • Filtering by Admin: If you want to filter results by a specific admin who performed the disable action, you can add another filter to the script:
  • 
        $adminEmail = Read-Host "Enter the admin's email address"
        $disabledBy = $event.InitiatedBy.User.UserPrincipalName
        if ($disabledBy -eq $adminEmail) {
            # Process event...
        }
    

Possible Errors & Solutions

Error 1: Insufficient Permissions

Error: "Insufficient privileges to complete the operation"

Cause: The account used to run the script does not have the required permissions (AuditLog.Read.All).

Solution: Ensure that the account has the appropriate role and permissions. You can assign the role via the Azure AD admin center.

Error 2: No Results Returned

Error: "No disabled user events found in the given date range."

Cause: There were no user disable actions in the specified time period, or the filters are too restrictive.

Solution: Expand the date range or check that the right action (Update user) is being captured in the logs.

Error 3: Invalid Date Format

Error: "Invalid DateTime format"

Cause: Date formats need to follow the ISO 8601 standard (yyyy-MM-ddTHH:mm:ssZ).

Solution: Ensure that the date is formatted correctly. You can also add error handling to the script to prompt the user in case of an incorrect format.

Conclusion

Disabling a user's account in Azure AD is a critical action, and having a record of these events is essential for audit and compliance purposes. The PowerShell script we’ve outlined provides a simple and effective way to track disabled users, allowing administrators to retrieve key details including the exact time of the action, the user affected, and the admin responsible.

By leveraging audit logs from Microsoft Graph, this script helps you maintain transparency and security in your organization’s user management practices. With further enhancements such as automated reporting or exporting the results, the script can become a powerful tool in your administrative toolkit.

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