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 tenantWrite-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 accountsClear-HostForEach ($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.displayNameIf ($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.LastSignInDateTimeIf ($Null -ne $UserLastLogonDate) {$UserLastLogonDate = Get-Date ($UserLastLogonDate) -format g} Else {$UserLastLogonDate = "No recent sign in records found"}$ReportLine = [PSCustomObject][Ordered]@{UPN = $Guest.UserPrincipalNameName = $Guest.DisplayNameAge = $AccountAge"Account created" = $Guest.createdDateTime"Last sign in" = $UserLastLogonDateGroups = $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
Author
Office365itpros