Get ADFS account activity (lockouts) for all users

Microsoft ADFS (Active Directory Federation Services) has a feature known as extranet lockout and extranet smart lockout. ADFS extranet smart lockout allows you to differentiate between sign-in attempts from unknown locations and known locations. Which in turn prevents users getting locked on the Active Directory domain.

Pro tip: this post relies on basic Windows PowerShell skills. I can highly recommend O’reilly’s PowerShell cookbook to improve your basic PowerShell skills.

When a user get’s locked out, ADFS has a PowerShell cmdlet know Get-ADFSAccountActivity to get the lock out status of one particular user. You can use the cmdlet as follows:

Get-AdfsAccountActivity -Identity <username>

The response of the command looks like this:

Identifier             : DOMAIN\Username
BadPwdCountFamiliar    : 0
BadPwdCountUnknown     : 6
LastFailedAuthFamiliar : 1-1-0001 01:00:00
LastFailedAuthUnknown  : 4-2-2020 12:36:11
FamiliarLockout        : False
UnknownLockout         : True
FamiliarIps            : {}

Unfortunately Microsoft has not provided us with a PowerShell cmdlet to get the lockout status for all users. I created two scripts to allow you to fetch the activity status of all users. This first script get’s all the userprincipalnames from the Active Directory. You need the ActiveDirectory PowerShell module for this.

The scripts

Here is the first script:

import-module ActiveDirectory
$users = Get-ADUser -SearchBase "OU=Users,DC=contoso,DC=local" -filter * | Select-Object -Property userprincipalname

$users | export-csv -NoTypeInformation C:\Development\PowerShell\users.csv

You need to modify the “SearchBase” to match you Active Directory structure. Furthermore you need to change the the path of the CSV file to match your export location. I ran this script from my Windows 10 administration machine.

The second script needs to be run on the ADFS server using “Run as Administrator” (administrative privileges):

$users = import-csv users.csv
$export_users = @()

foreach ($user in $users)
{
    try {
        # Get ADFS activity
        $activity = Get-AdfsAccountActivity -Identity $user.UserPrincipalName
        if ($activity.UnknownLockout -eq $true -or $activity.FamiliarLockout -eq $true) {

            $export_user = New-Object PSObject -Property @{
                Username         = $activity.identifier
                UnknownLockout   = $activity.UnknownLockout
                FamiliarLockout  = $activity.FamiliarLockout
            }

            $export_users += $export_user

        }
    } catch {
        # Catch condition when user is not in ADFS database.
    }
}

# Export users to HTML file
$export_users | ConvertTo-Html | out-file report.html

As you can see the second script requires an input CSV file which we generated using script 1. The script will generate a HTML file with the username and whether it is locked out on either the familiar or unknown locations.