How to Fetch Hard Deleted Users Using Graph PowerShell

When managing user accounts in Microsoft 365, it's crucial to track actions like hard deletions—permanent removals of user identities from Azure AD. Knowing who was deleted, when, and by whom is vital for security, compliance, and auditing. In this article, we’ll walk through a Graph PowerShell script that fetches hard deleted users using Azure AD audit logs


The Script

The following script queries Azure AD audit logs for the activity "Delete user", indicating a hard deletion. It retrieves and displays the:

  • Deleted Time
  • Deleted User (UserPrincipalName)
  • Deleted By (administrator or identity that performed the deletion)
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "AuditLog.Read.All"
                                
# Define the timeframe (last 30 days)
$startDateTime = (Get-Date).AddDays(-30).ToString("yyyy-MM-ddTHH:mm:ssZ")
                                
# Fetch audit logs where users were permanently deleted
$deletedUserLogs = Get-MgAuditLogDirectoryAudit -Filter "activityDisplayName eq 'Hard Delete user' and activityDateTime ge $startDateTime"
                                
# Create array to store hard deleted users
$hardDeletedUsers = @()
                                
# Loop through the logs to extract user info
foreach ($event in $deletedUserLogs) {
    $deletedTime = $event.ActivityDateTime
    $deletedUser = ($event.TargetResources | Where-Object { $_.UserPrincipalName }).UserPrincipalName
    $deletedBy = $event.InitiatedBy.User.UserPrincipalName
    $resultStatus = if ($event.Result -eq 'success') { 'Success' } else { 'Failed' }
                                    
    # Only include successfully deleted users
    if ($resultStatus -eq 'Success' -and $deletedUser) {
        $record = [PSCustomObject]@{
            "Deleted Time"     = $deletedTime
            "Deleted User"     = $deletedUser
            "Deleted By"       = $deletedBy
        }
     $hardDeletedUsers += $record
    }
}
                                
# Output the results
if ($hardDeletedUsers.Count -eq 0) {
    Write-Host "No hard deleted users found in the last 30 days."
} else {
    $hardDeletedUsers | Format-Table -AutoSize
}
                                

How the Script Works

  1. Connection: Uses Connect-MgGraph to authenticate to Microsoft Graph with the AuditLog.Read.All scope.
  2. Timeframe: Pulls data from the past 30 days (customizable via AddDays(-30)).
  3. Log Filtering: Looks specifically for the activity "Delete user" using Get-MgAuditLogDirectoryAudit.
  4. Data Extraction: Retrieves UserPrincipalName, DisplayName, and InitiatedBy info from each matching audit log entry.
  5. Result Filtering: Only includes logs where the deletion action was successful.
  6. Output: Displays a clean, formatted table with relevant user deletion details.

Further Enhancements

Here are ways you can extend or customize the script:

Change the Date Range

$startDateTime = (Get-Date).AddDays(-90).ToString("yyyy-MM-ddTHH:mm:ssZ")  # Last 90 days

Export the Results to a CSV

$hardDeletedUsers | Export-Csv -Path "HardDeletedUsers.csv" -NoTypeInformation

Filter by Admin Identity

Want to track deletions by a specific admin?

Where-Object { $_.DeletedBy -eq "admin@yourdomain.com" }

Use Cases

Here’s where this script is particularly useful:

  • Security Audits – Know exactly when and who performed permanent deletions.
  • Compliance Reviews – Document user removals for audits and governance.
  • Accidental Deletion Checks – Trace deleted accounts to validate whether the deletion was authorized.
  • Admin Oversight – Monitor the actions of privileged users within the tenant.

Possible Errors & Solutions

Error Cause Solution
Access Denied or Insufficient Permissions Missing required permission scopes. Connect using: Connect-MgGraph -Scopes "AuditLog.Read.All"
The term 'Get-MgAuditLogDirectoryAudit' is not recognized Graph module is not installed Install-Module Microsoft.Graph -Scope CurrentUser Import-Module Microsoft.Graph
No Results Found No hard deletions in the date range Extend the date range or verify that audit logging is enabled in your tenant.

Conclusion

Tracking hard deleted users is a critical part of Microsoft 365 administration. Whether you're preparing for an audit, investigating suspicious activity, or maintaining clean records, this Graph PowerShell script provides a clear, efficient way to retrieve deletion data from your Azure AD audit logs.

Use this script to strengthen your security posture, maintain accountability, and ensure compliance across your organization.


Graph PowerShell Explorer Widget

20 Graph PowerShell cmdlets with easily accessible "working" examples.


Permission Required

Example:


                


                


                

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