How to find Stale(ish) Azure B2B Guest Accounts

If you are utilizing external, guest, or B2B users in your Office 365 or Azure environments, you may need a way to determine which objects haven't been logged in or used in a while.  Azure AD doesn't provide an easy way to view this information (really only having the refresh token time available).  This method doesn't complete solve the question of stale B2B accounts, but I think it's a good stab at it.

This script uses the RefreshTokensValidFromDateTime property from the user in conjunction with one of the following:

  • default token refresh lifetime in Azure AD (90 days)
  • the actual token refresh lifetime if a policy has been configured and is able to be read
  • a user-specified value

This will help you identify when users last logged on (using the RefreshTokensValidFromDateTimeProperty), and then, based on the tenant's refresh token setting and a "stale" value (how long you want to specify without a refresh token being updated), lets you calculate a stale user. The additional value, specified in the the StaleAgeInDays parameter, is added to the one of the three previous tenant token times.  If the user's refresh token is older than that value, the user is "stale."

The main logic:

 $Filter = "UserType eq 'Guest'"
$Guests = Get-AzureADUser -All $true -Filter $Filter

# Calculate users whose last STS refresh token value is 'n' past expiration
# For example, if token expiration is 90 days, and StaleAgeInDays is 180, then
# return objects that have a token age 270 days ago
$Today = (Get-Date)
$Global:StaleUsers = $Guests | ForEach-Object {
    $TimeStamp = $_.RefreshTokensValidFromDateTime
    $TimeStampString = $TimeStamp.ToString()
    [int]$LogonAge = [math]::Round(($Today - $TimeStamp).TotalDays)
    [int]$StaleAge = $MaxInactiveTime + $StaleAgeInDays
    $User = $($_.Mail)
    If ($LogonAge -ge $StaleAge)
    {
        [pscustomobject]@{
            User        = $($User)
            ObjectID    = $_.ObjectID
            IsStale     = "True"
            LastLogon   = $TimeStamp
            DaysSinceLastLogon = $LogonAge
            UserIsStaleAfterThisManyDays = $StaleAge
        }
    }
}

You can download the full script at https://gallery.technet.microsoft.com/Report-on-Azure-AD-Stale-8e64c1c5.