1. The Workflow
  2. The Implementation

External guest accounts are frequently provisioned for vendors but rarely decommissioned, creating a lingering attack surface. This script uses the Microsoft Graph API to identify and remove guest accounts that have been inactive for over 90 days.

1. The Workflow

The script performs the following steps:

  • Authentication: Uses App Registration credentials to silently authenticate to MS Graph.
  • Filtering: Queries all users where userType equals “Guest”.
  • Evaluation: Checks the signInActivity property against a 90-day threshold.
  • Purge: Identifies stale guest accounts to close the security loop.

2. The Implementation

$ThresholdDate = (Get-Date).AddDays(-90).ToString("yyyy-MM-ddTHH:mm:ssZ")
$Url = "[https://graph.microsoft.com/beta/users](https://graph.microsoft.com/beta/users)?`$filter=userType eq 'Guest'&`$select=displayName,userPrincipalName,signInActivity"
$Guests = Invoke-RestMethod -Uri $Url -Method Get -Headers $Headers

foreach ($Guest in $Guests.value) {
    if ([string]::IsNullOrEmpty($Guest.signInActivity.lastSignInDateTime) -or ($Guest.signInActivity.lastSignInDateTime -lt $ThresholdDate)) {
        Write-Host "Stale Guest Found: $($Guest.displayName)"
    }
}