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.