We deployed Microsoft Entra Password Protection to our on-premises domain controllers and, like Microsoft recommends, left it in Audit mode. That’s the easy part. The harder question comes later: when is it actually safe to switch to Enforced?
The official answer is “once you’ve assessed the impact”, which is sensible but not very specific. The event logs are full of IDs that look alike, the summary report has a quirk that can make the numbers misleading, and there’s a fundamental limit on what Audit mode can tell you that’s easy to overlook.
This article covers how to read the audit data properly, what it can and can’t tell you, how to turn it into a decision, and what to sort out before you flip the switch, so the first week of enforcement isn’t a week of helpdesk calls.
How it works, briefly
Password Protection extends Entra ID’s banned password checks to on-premises Active Directory. A proxy service downloads the password policy from Entra ID, and an agent on each domain controller uses it to check every new password. The policy combines Microsoft’s global banned password list with any custom banned terms you add, such as your company name, products or local sports teams. Using it for on-premises AD needs Microsoft Entra ID P1 or P2 licences for the users it covers, so check that before you plan around it.
Two details matter for everything that follows.
First, the agent only checks a password when it’s changed or set. It never looks at passwords people already have. A weak password chosen three years ago stays exactly as it is until the user next changes it.
Second, the Audit and Enforced modes only apply to on-premises Active Directory. In Audit mode, the agent evaluates each new password and logs whether it would have been rejected, but accepts it anyway. In Enforced mode, the same password is refused. Nothing else about the check changes, which is what makes Audit mode useful: it shows you exactly what enforcement would have done.
Reading the audit data
Everything you need is in the Microsoft-AzureADPasswordProtection-DCAgent/Admin event log on each domain controller. Each password check writes a pair of events: a summary event that says whether the password passed, and a detail event that says which policy it would have failed.
The summary events are the ones to know (Microsoft Learn: Monitor on-premises Microsoft Entra Password Protection):
| Outcome | Password change | Password set or reset |
|---|---|---|
| Passed | 10014 | 10015 |
| Rejected | 10016 | 10017 |
| Would have been rejected, accepted because of Audit mode | 10024 | 10025 |
The difference between a change and a set matters. A change is a user changing their own password, knowing the old one. A set is a password set or reset by someone else, usually the helpdesk or an admin, or an automated process. Keep that in mind, because the two often tell very different stories.
The summary report, and a quirk worth knowing
Rather than reading events one at a time, the PowerShell module includes Get-AzureADPasswordProtectionSummaryReport, which counts the events and summarises them. Run it against each domain controller, because each one only holds the events for the passwords it processed:
Get-AzureADPasswordProtectionSummaryReport -DomainController dc01.example.localIts PasswordChangeAuditOnlyFailures and PasswordSetAuditOnlyFailures counts are the audit numbers you want. But there’s a trap. In Microsoft’s own event table, a password that would have failed only because it contains the user’s name is logged in Audit mode with the rejected IDs, 10016 and 10017, paired with detail events 30024 and 30023. So while you’re still in Audit mode, some of the “rejected” counts aren’t rejections at all. They’re user name matches that were accepted.
If your Audit-mode report shows rejections and you’re wondering how that’s possible, check the detail events. If they’re 30023 or 30024, nothing was actually blocked. Count them with the audit-only failures, because those passwords will be rejected once you enforce.
The catch: Audit mode only sees passwords that change
This is the limit that’s easiest to overlook. Because the agent only checks new passwords, Audit mode only tells you about the people who happened to change their password while it was running. It says nothing about everyone else.
That has a big effect on how long you need to wait, and it depends on your password policy.
If you still force passwords to expire every 90 days, a 90-day audit window covers almost every active user. You’ll see close to the full picture of who would be affected.
If you’ve stopped routine password expiry, as NIST’s digital identity guidelines recommend and many organisations now do, passwords mostly change only when someone forgets theirs or there’s a security reason. In that case, even six months of audit data might cover a fairly small slice of your users. A quiet audit log doesn’t mean nobody has a weak password. It may just mean hardly anybody changed one.
So before you read anything into the numbers, work out how many passwords were actually checked. This compares how many enabled users have changed their password since the audit started with the total:
$auditStart = Get-Date '2026-07-01'
$users = Get-ADUser -Filter 'Enabled -eq $true' -Properties PasswordLastSet
$changed = $users | Where-Object { $_.PasswordLastSet -ge $auditStart }
"{0} of {1} enabled users have set a password since Audit mode started ({2:P0})" -f $changed.Count, $users.Count, ($changed.Count / $users.Count)If that percentage is small, you have two choices. Wait longer, or accept that Audit mode has shown you the pattern rather than the full count, and plan your communications for a larger impact than the logs suggest. Either is reasonable. What isn’t reasonable is treating a quiet log as proof that enforcement will be painless.
Turning the data into a decision
The summary report gives you counts. To make a decision, you need names and patterns. This pulls the relevant events from every domain controller into one spreadsheet, with the user name taken from the event text:
$dcs = (Get-ADDomainController -Filter *).HostName
$ids = 10016, 10017, 10024, 10025
Invoke-Command -ComputerName $dcs -ScriptBlock {
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-AzureADPasswordProtection-DCAgent/Admin'
Id = $using:ids
} -ErrorAction SilentlyContinue |
ForEach-Object {
[pscustomobject]@{
Time = $_.TimeCreated
EventId = $_.Id
User = if ($_.Message -match 'UserName:\s*(\S+)') { $Matches[1] } else { '' }
}
}
} | Select-Object PSComputerName, Time, EventId, User |
Export-Csv .\password-protection-audit.csv -NoTypeInformationThe event log on each domain controller has a size limit, so older events eventually roll off. If your audit period is long, run an export like this regularly rather than relying on the history still being there at the end.
With the data in front of you, look for three things.
How many people, not how many events. One person might trigger several audit failures in a row while trying variations of the same weak password. The number of distinct users is what tells you how many people will need help.
Sets versus changes. This is often the most revealing split. A cluster of 10025 events, password sets that would have failed, usually points at a process rather than at users. The classic example is a helpdesk that resets passwords to something predictable, like the season and the year. Enforcement will break that process on day one, so fix it first.
Which policy caught them. The agent never logs the password itself, but the detail events tell you why it would have failed: Microsoft’s global list, your custom list, a combination, or the user’s own name. If most failures come from your custom list, your terms are doing their job, and they tell you what to mention when you explain the change to staff. If user name matches dominate, that’s a simple, specific message to give people: don’t put your name in your password.
When the distinct number of affected users is manageable, the helpdesk process is fixed, and you understand the patterns, you’re ready. There’s no magic number. It’s a judgement about whether your helpdesk can absorb the calls.
Before you switch: users, helpdesk and accounts
Most of the pain from enforcement comes from things you can sort out in advance, and the biggest one is the error message.
When the agent rejects a password, Windows shows its standard message saying the password doesn’t meet the policy requirements. It doesn’t mention a banned list. So a user who hasn’t been told about the change does the obvious thing: adds another number or symbol, gets refused again, and calls the helpdesk. A short note before enforcement saves a lot of those calls. Explain that common words, the company name and people’s own names are now blocked, and suggest a passphrase made of several unrelated words instead.
The helpdesk needs the same briefing, plus one extra job. If they reset passwords to something predictable, those resets will start failing on the first day, so change that process before you switch. The same goes for anything that sets passwords automatically, such as provisioning tools, scripts or third-party systems. A randomly generated password will almost always pass. One built from a pattern, like a product name and a year, may not, and the 10025 events from your audit period will show you which ones have been caught.
It’s also a good moment to review the custom banned list. Include the terms that genuinely matter for your organisation, such as the company name, brands, products, local places and sports teams, without making it so broad that reasonable passphrases get blocked.
Finally, make sure every domain controller is covered. A domain controller without the agent doesn’t check passwords at all, so any change it processes slips straight through. The module can list the agents that have registered, along with their last heartbeat, which makes it easy to compare against your full list of domain controllers:
$registered = Get-AzureADPasswordProtectionDCAgent | Select-Object -ExpandProperty ServerFQDN
$allDCs = (Get-ADDomainController -Filter *).HostName
$allDCs | Where-Object { $_ -notin $registered }Anything that command returns is a domain controller without a registered agent. Check new domain controllers in particular, since they’re easy to add without remembering the agent.
Switching to Enforced, and what to watch afterwards
The switch itself is a single setting. In the Microsoft Entra admin centre, open the Password protection settings under authentication methods, make sure password protection is enabled for Windows Server Active Directory, and change the mode from Audit to Enforced.
It doesn’t take effect on every domain controller instantly. The agents pick up the updated policy on their next refresh. Microsoft’s own testing guidance cycles the DC agent service to apply a new policy straight away, which is useful if you want to confirm the change on a test domain controller first (Microsoft Learn: On-premises Password Protection FAQ).
Once it’s live, the events to watch change. The audit-only events 10024 and 10025 stop, and real rejections appear as 10016 for changes and 10017 for sets. Keep an eye on them for the first few weeks:
- A spike in 10017 usually means a reset process or a provisioning tool you missed.
- The same user appearing repeatedly in 10016 is someone stuck trying variations of a banned password, and worth a friendly call before they give up and ring you.
- A user name match (detail events 30021 and 30022) is a good chance to repeat the simplest advice: don’t use your name.
If something important breaks, you can switch back to Audit mode just as easily while you fix it. That safety net is worth knowing about, but it shouldn’t be your plan. The preparation above is what keeps the first weeks of enforcement uneventful.
Checklist: moving from Audit to Enforced
- Remember that only changed and set passwords are checked, never existing ones.
- Read the DCAgent Admin log on every domain controller, or run
Get-AzureADPasswordProtectionSummaryReportagainst each one. - In Audit mode, treat 10016 or 10017 events paired with 30023 or 30024 as user name matches that were accepted, not real rejections.
- Work out what share of users actually changed a password during the audit, before trusting the numbers.
- Export the events regularly, so older ones don’t roll off before you analyse them.
- Count distinct users, split sets from changes, and note which policy caught them.
- Fix any helpdesk or provisioning process that sets predictable passwords.
- Tell users in advance, and give them simple passphrase advice.
- Confirm the agent is installed and running on every domain controller.
- Switch to Enforced, then watch 10016 and 10017 for the first few weeks.
Audit mode is there to take the guesswork out of enforcement, but only if you understand what it’s measuring. It shows you the people who changed a password, not everyone with a weak one. Read it with that in mind, fix the processes it exposes, and the switch to Enforced becomes a routine change rather than a leap of faith.
Sources
- Microsoft Learn: Monitor and review logs for on-premises Microsoft Entra Password Protection
- Microsoft Learn: On-premises Microsoft Entra Password Protection FAQ

From my early days on the helpdesk through roles as a service desk manager, systems administrator, and network engineer, I’ve spent more than 25 years in the IT world. As I transition into cyber security, my goal is to make tech a little less confusing by sharing what I’ve learned and helping others wherever I can.

