Passwords and MFA: what the standards recommend and how to apply it in Active Directory
Forced password changes every 90 days and “upper case, digit, special character” rules are advice the standards have abandoned. What replaced them, how to check your current domain settings, and which MFA methods resist phishing.
In many organisations the password policy has looked the same for years: at least eight characters, an upper-case letter, a digit, a special character, a change every 90 days, no reuse of the last 24. The result is predictable: Spring2026!, then Summer2026!, sticky notes under keyboards and a series of reset requests every Monday after a change. An account with the password Summer2026! and no second factor falls to the first attack that tries a few popular passwords against every account in the organisation.
The standards these rules were based on dropped them long ago. Below: what replaced them, how to check your current domain settings, and which MFA methods actually protect against phishing.
What the current guidance says
The most frequently cited reference is NIST’s authentication guidance, SP 800-63B revision 4.
| Previous rule | Current recommendation | Reason |
|---|---|---|
| at least 8 characters with complexity required | at least 15 characters when the password is the only factor, 8 with MFA; no requirements on character types | composition rules produce predictable patterns, length produces resistance |
| a change every 30–90 days | a change only when there is evidence of exposure | forced changes produce successive versions of the same password |
| no check of the password’s content | comparison against a blocklist: common, dictionary, organisation-related and breached passwords | attackers start from the same lists |
| a short length limit, no pasting | at least 64 characters, pasting allowed | passphrases and password managers |
| security questions and hints | none | the answers are easy to find in public sources |
Applying it in Active Directory
The password policy for domain accounts comes from a Group Policy Object linked to the root of the domain, usually the Default Domain Policy, under Computer Configuration → Policies → Windows Settings → Security Settings → Account Policies → Password Policy. The same settings linked to an organisational unit apply only to computers’ local accounts, not to domain accounts.
The classic policy caps the minimum length at 14 characters. Newer versions of Windows Server allow going beyond that limit with the “Relax minimum password length limits” setting in the same node, and the “Minimum password length audit” setting lets you first collect, in the domain controllers’ event logs, information about passwords being set that are shorter than the planned minimum. Every domain controller must support the mechanism, so the rollout starts with the audit.
A longer minimum for selected accounts comes from a Fine-Grained Password Policy. It applies to users and global security groups, when several policies apply the one with the lower Precedence wins, and the minimum length is not subject to the 14-character limit. Length requirements take effect at the group members’ next password change:
New-ADFineGrainedPasswordPolicy -Name 'PSO-Admins' -Precedence 10 `
-MinPasswordLength 20 -ComplexityEnabled $true -PasswordHistoryCount 24 `
-MinPasswordAge '1.00:00:00' -MaxPasswordAge '365.00:00:00' `
-LockoutThreshold 10 -LockoutDuration '00:15:00' -LockoutObservationWindow '00:15:00'
Add-ADFineGrainedPasswordPolicySubject -Identity 'PSO-Admins' -Subjects 'GG-Admins-Tier0'
Complexity stays enabled until the blocklist is in place, because in AD on its own it is the only mechanism that rejects a password containing the account name. Expiry after a year stays for the same reason.
A blocklist of banned passwords
Microsoft Entra Password Protection for AD DS consists of an agent on every domain controller and a proxy service that downloads the lists from Entra ID. A new password is compared against a global list of weak passwords and the organisation’s own list (up to 1000 entries: company name, products, city, sports team names), after normalising common substitutions, so P@ssw0rd is treated as password. The service requires an Entra ID P1 licence or higher and has an audit mode, which is the place to start. The alternative is open-source password filters on the domain controllers that check passwords against a list of known breaches, such as Lithnet Password Protection.
The blocklist applies when a password is changed or reset, not at sign-in. Existing weak passwords remain until the next change.
Accounts the policy does not cover
An account with PasswordNeverExpires set is not subject to expiry, and a service account whose password was set eight years ago is usually written into several scripts. Group Managed Service Accounts (gMSA) have passwords generated and changed automatically by the domain, so every service account that can be a gMSA should be one. Get-ADServiceAccount -Filter * lists the existing gMSAs.
User accounts with an SPN deserve particular attention: any authenticated domain user can request a Kerberos ticket for them and try to crack the password offline. An account with an SPN and an old, short password is a ready-made target:
Get-ADUser -Filter "ServicePrincipalName -like '*'" -Properties ServicePrincipalName, PasswordLastSet |
Select-Object SamAccountName, PasswordLastSet, ServicePrincipalName
Every such account is a candidate for a gMSA, and until it is migrated it gets a random password of at least 25 characters from the secrets manager.
MFA: not all of it is equal
| Method | Phishing resistance | Convenience | Cost |
|---|---|---|---|
| SMS, voice call | no: number takeover, a code that can be typed into a fake site | medium | none, or SMS charges |
| One-time code from an app (TOTP) | no: the code can be typed into a fake site | medium | none |
| Push notification with number matching | no: protects against prompt flooding, but not against a relaying site | high | none |
| Passkey in an authenticator app | yes | high | no extra hardware |
| Windows Hello for Business | yes | very high on one’s own computer | a TPM, a deployment project |
| FIDO2 hardware key | yes | high | buying keys, ideally two per person |
| Certificate, smart card | yes | medium | PKI infrastructure, cards and readers |
The difference between the top and bottom of the table is qualitative. A relaying site in an adversary-in-the-middle attack passes the password, the code and the push approval to the real service, and takes over the session after sign-in. Phishing-resistant methods sign a challenge with a key bound to the site address, so a signature generated for a fake domain is useless.
Rollout order: administrators first, straight to phishing-resistant methods enforced in Conditional Access with the built-in “Phishing-resistant MFA” authentication strength (requires Entra ID P1). Then remote access and email, then all users. Legacy authentication, which cannot do a second factor, is blocked. The only exceptions are emergency access accounts, covered by a separate procedure and monitoring.
Check your own environment
The domain’s default password policy:
Get-ADDefaultDomainPasswordPolicy |
Format-List MinPasswordLength, ComplexityEnabled, MaxPasswordAge, PasswordHistoryCount, LockoutThreshold
MinPasswordLength : 8
ComplexityEnabled : True
MaxPasswordAge : 90.00:00:00
PasswordHistoryCount : 24
LockoutThreshold : 0
A MinPasswordLength below 14 with the password as the only factor is too little. A LockoutThreshold of 0 means no account lockout, so an unlimited number of attempts; a sensible value is, for example, 10 attempts.
Fine-grained password policies, and the policy that actually applies to a specific account:
Get-ADFineGrainedPasswordPolicy -Filter * |
Format-Table Name, Precedence, MinPasswordLength, MaxPasswordAge, AppliesTo
Get-ADUserResultantPasswordPolicy -Identity adm.jkowalski
No output from the first command means administrators have the same requirements as everyone else. No output from the second means the account is subject to the default policy, not a fine-grained one.
Enabled accounts whose password never expires, oldest password first:
Get-ADUser -Filter 'PasswordNeverExpires -eq $true -and Enabled -eq $true' -Properties PasswordLastSet, LastLogonDate |
Sort-Object PasswordLastSet |
Format-Table SamAccountName, PasswordLastSet, LastLogonDate
Every account on the list should have an owner and a justification. Personal accounts on this list, and service accounts with a password several years old, are the first candidates for change.
Authentication methods enabled in Entra ID:
Connect-MgGraph -Scopes 'Policy.Read.All'
(Get-MgPolicyAuthenticationMethodPolicy).AuthenticationMethodConfigurations |
Format-Table Id, State
A good result: Fido2 and MicrosoftAuthenticator enabled, Sms and Voice disabled or limited to a transitional group. SMS enabled for everyone means some users rely on the weakest method, because it is the most convenient at registration.