How to Configure AD Fine-Grained Password Policies on Windows Server 2025

Active Directory’s default password policy applies uniformly to every user in a domain — a single set of rules governing minimum length, complexity, lockout thresholds, and maximum age. For most organisations this one-size-fits-all approach is too blunt: service accounts need longer, never-expiring passwords while privileged administrator accounts require stricter lockout controls. Fine-Grained Password Policies (FGPPs), introduced with Windows Server 2008 Active Directory and fully supported on Windows Server 2025, solve this by allowing multiple password policies to coexist in the same domain. Each policy is stored as a Password Settings Object (PSO) in Active Directory and can be applied to individual users or global security groups. This tutorial walks through every step of planning, creating, applying, and verifying FGPPs on a Windows Server 2025 domain.

Prerequisites

  • The domain must be running at Windows Server 2008 domain functional level or higher. On Windows Server 2025 domains this is satisfied automatically, but verify with Get-ADDomain | Select DomainMode.
  • You must be a member of the Domain Admins group, or have been delegated control over the Password Settings Container in Active Directory.
  • The Active Directory PowerShell module must be available. Install it via RSAT if needed: Add-WindowsFeature RSAT-AD-PowerShell.
  • A test user account and at least one global security group should exist in the domain for the hands-on steps.

Step 1: Understand How FGPPs Work

FGPPs are stored inside the Password Settings Container (CN=Password Settings Container,CN=System,DC=domain,DC=com). Each PSO object holds every attribute that a traditional password policy contains — plus a Precedence value that resolves conflicts when a user belongs to multiple groups that have different PSOs applied. Lower precedence numbers win; a value of 1 takes priority over 10.

When Active Directory evaluates which password policy applies to a user, it follows this logic:

  1. If a PSO is linked directly to the user object, that PSO applies regardless of group membership.
  2. If no direct link exists, AD collects all PSOs linked to the user’s global security groups, then applies the one with the lowest precedence number.
  3. If no PSO applies, the domain’s Default Domain Policy (configured via Group Policy) governs the account.

Step 2: Verify Domain Functional Level

Open an elevated PowerShell session on a domain controller and confirm the domain functional level:

# Import the AD module (already available on a DC)
Import-Module ActiveDirectory

# Check domain functional level
Get-ADDomain | Select-Object Name, DomainMode

# Expected output on a WS 2025 domain:
# Name        DomainMode
# ----        ----------
# corp        Windows2016Domain  (or higher)

Any value of Windows2008Domain or higher supports FGPPs. If the level is lower, raise it with Set-ADDomainMode after upgrading all domain controllers.

Step 3: Create a Password Settings Object

Use New-ADFineGrainedPasswordPolicy to create a PSO. The example below creates a strict policy for privileged administrator accounts:

New-ADFineGrainedPasswordPolicy `
    -Name "PSO-PrivilegedAdmins" `
    -DisplayName "Privileged Admin Password Policy" `
    -Description "Stricter password rules for Domain Admins and Tier-0 accounts" `
    -Precedence 10 `
    -MinPasswordLength 20 `
    -PasswordHistoryCount 24 `
    -ComplexityEnabled $true `
    -ReversibleEncryptionEnabled $false `
    -MaxPasswordAge "60.00:00:00" `
    -MinPasswordAge "1.00:00:00" `
    -LockoutThreshold 3 `
    -LockoutDuration "00:30:00" `
    -LockoutObservationWindow "00:30:00"

Now create a more lenient policy for service accounts that never expire and have higher lockout tolerance:

New-ADFineGrainedPasswordPolicy `
    -Name "PSO-ServiceAccounts" `
    -DisplayName "Service Account Password Policy" `
    -Description "Long, non-expiring passwords for managed service accounts" `
    -Precedence 20 `
    -MinPasswordLength 30 `
    -PasswordHistoryCount 12 `
    -ComplexityEnabled $true `
    -ReversibleEncryptionEnabled $false `
    -MaxPasswordAge "0.00:00:00" `
    -MinPasswordAge "0.00:00:00" `
    -LockoutThreshold 0 `
    -LockoutDuration "00:00:00" `
    -LockoutObservationWindow "00:00:00"

Note: MaxPasswordAge "0.00:00:00" means the password never expires. LockoutThreshold 0 disables lockout — appropriate for service accounts where a lockout would cause service outages.

Step 4: Apply the PSO to Groups or Users

PSOs are applied using Add-ADFineGrainedPasswordPolicySubject. The subject can be a global security group (recommended) or an individual user.

# Apply the privileged admin policy to the Domain Admins group
Add-ADFineGrainedPasswordPolicySubject `
    -Identity "PSO-PrivilegedAdmins" `
    -Subjects "Domain Admins"

# Apply to a custom Tier-0 admins group
Add-ADFineGrainedPasswordPolicySubject `
    -Identity "PSO-PrivilegedAdmins" `
    -Subjects "Tier0-Administrators"

# Apply the service account policy to a dedicated group
Add-ADFineGrainedPasswordPolicySubject `
    -Identity "PSO-ServiceAccounts" `
    -Subjects "GRP-ServiceAccounts"

# Apply directly to a specific user (overrides all group-based PSOs)
Add-ADFineGrainedPasswordPolicySubject `
    -Identity "PSO-PrivilegedAdmins" `
    -Subjects "svc-critical"

Step 5: Verify PSO Configuration and Effective Policy

After applying PSOs, verify settings and confirm which policy a specific user actually receives:

# List all PSOs in the domain
Get-ADFineGrainedPasswordPolicy -Filter * | 
    Select-Object Name, Precedence, MinPasswordLength, LockoutThreshold, MaxPasswordAge

# View full details of a specific PSO
Get-ADFineGrainedPasswordPolicy -Identity "PSO-PrivilegedAdmins" | Format-List *

# See which groups/users a PSO is applied to
Get-ADFineGrainedPasswordPolicySubject -Identity "PSO-PrivilegedAdmins"

# Determine the RESULTANT policy for a specific user
# (accounts for precedence and direct links)
Get-ADUserResultantPasswordPolicy -Identity "jsmith"

The Get-ADUserResultantPasswordPolicy cmdlet is the definitive tool for auditing: it returns the single effective PSO that will govern the user’s next password change, or nothing if the default domain policy applies.

Step 6: Modify an Existing PSO

Adjust PSO settings without recreating it using Set-ADFineGrainedPasswordPolicy:

# Increase minimum length for privileged admins to 24 characters
Set-ADFineGrainedPasswordPolicy `
    -Identity "PSO-PrivilegedAdmins" `
    -MinPasswordLength 24 `
    -MaxPasswordAge "30.00:00:00"

# Change lockout threshold
Set-ADFineGrainedPasswordPolicy `
    -Identity "PSO-PrivilegedAdmins" `
    -LockoutThreshold 5 `
    -LockoutDuration "01:00:00"

Step 7: Remove a PSO Subject or Delete a PSO

# Remove a group from a PSO
Remove-ADFineGrainedPasswordPolicySubject `
    -Identity "PSO-ServiceAccounts" `
    -Subjects "GRP-ServiceAccounts" `
    -Confirm:$false

# Delete the PSO entirely (all subject links are removed automatically)
Remove-ADFineGrainedPasswordPolicy `
    -Identity "PSO-ServiceAccounts" `
    -Confirm:$false

Step 8: Audit FGPPs Across the Domain

Generate a compliance report showing every PSO and its effective subjects:

$psos = Get-ADFineGrainedPasswordPolicy -Filter * | Sort-Object Precedence

foreach ($pso in $psos) {
    Write-Host "`n=== $($pso.Name) (Precedence: $($pso.Precedence)) ===" -ForegroundColor Cyan
    Write-Host "  Min Length   : $($pso.MinPasswordLength)"
    Write-Host "  Complexity   : $($pso.ComplexityEnabled)"
    Write-Host "  Max Age      : $($pso.MaxPasswordAge)"
    Write-Host "  Lockout      : $($pso.LockoutThreshold) attempts"
    
    $subjects = Get-ADFineGrainedPasswordPolicySubject -Identity $pso.Name
    Write-Host "  Applied To   : $($subjects.Name -join ', ')"
}

Conclusion

Fine-Grained Password Policies give Active Directory administrators precise control over password and lockout settings without resorting to separate domains or multiple forests. On Windows Server 2025, the combination of the ActiveDirectory PowerShell module and the Password Settings Container makes it straightforward to define distinct policies for privileged accounts, standard users, and service accounts. By assigning lower precedence numbers to more restrictive PSOs and applying them to targeted global security groups, you ensure the right level of security is enforced for each account class — while the default domain policy remains the safety net for any account not explicitly covered by a PSO.