Back to script library
Entra / Microsoft 365 · Users & guests

Find old Entra ID guest users

Find Entra ID guest user accounts older than 365 days (adjust the age threshold as needed) and report the groups they belong to.

Connect & set up

Run these once per session. All scopes are read-only unless the script makes changes.

Connect-MgGraph -Scopes AuditLog.Read.All, Directory.Read.All -NoWelcome

Run it

The main script. Copy it, or download the .ps1 and run it from your console.

Connect-MgGraph -Scopes AuditLog.Read.All, Directory.Read.All -NoWelcome
# Set age threshold for reporting a guest account
[int]$AgeThreshold = 365
# Output report name
$OutputReport = "c:\Temp\OldGuestAccounts.csv"
# Get all guest accounts in the tenant
Write-Host "Finding Guest Accounts..."
[Array]$GuestUsers = Get-MgUser -Filter "userType eq 'Guest'" -All -PageSize 999 -Property Id, displayName, userPrincipalName, createdDateTime, signInActivity `
| Sort-Object displayName
$i = 0; $Report = [System.Collections.Generic.List[Object]]::new()
# Loop through the guest accounts looking for old accounts
Clear-Host
ForEach ($Guest in $GuestUsers) {
# Check the age of the guest account, and if it's over the threshold for days, report it
$AccountAge = ($Guest.CreatedDateTime | New-TimeSpan).Days
$i++
If ($AccountAge -gt $AgeThreshold) {
$ProgressBar = "Processing Guest " + $Guest.DisplayName + " " + $AccountAge + " days old " + " (" + $i + " of " + $GuestUsers.Count + ")"
Write-Progress -Activity "Checking Guest Account Information" -Status $ProgressBar -PercentComplete ($i/$GuestUsers.Count*100)
$StaleGuests++
$GroupNames = $Null
# Find what Microsoft 365 Groups the guest belongs to... if any
[array]$GuestGroups = (Get-MgUserMemberOf -UserId $Guest.Id).additionalProperties.displayName
If ($GuestGroups) {
$GroupNames = $GuestGroups -Join ", "
} Else {
$GroupNames = "None"
}
# Find the last sign-in date for the guest account, which might indicate how active the account is
$UserLastLogonDate = $Null
$UserLastLogonDate = $Guest.SignInActivity.LastSignInDateTime
If ($Null -ne $UserLastLogonDate) {
$UserLastLogonDate = Get-Date ($UserLastLogonDate) -format g
} Else {
$UserLastLogonDate = "No recent sign in records found"
}
$ReportLine = [PSCustomObject][Ordered]@{
UPN = $Guest.UserPrincipalName
Name = $Guest.DisplayName
Age = $AccountAge
"Account created" = $Guest.createdDateTime
"Last sign in" = $UserLastLogonDate
Groups = $GroupNames }
$Report.Add($ReportLine) }
} # End Foreach Guest
$Report | Export-CSV -NoTypeInformation $OutputReport
$PercentStale = ($StaleGuests/$GuestUsers.Count).toString("P")
Write-Host ("Script complete. {0} guest accounts found aged over {1} days ({2} of total). Output CSV file is in {3}" -f $StaleGuests, $AgeThreshold, $PercentStale, $OutputReport)
Attribution