Helpdesk: "Since the patch weekend, about a third of the laptops can't join the CORP-SECURE Wi-Fi, and some new Always On VPN users get rejected too. The NPS server's Security log is full of Event 6273. Most say reason code 16, a few say reason code 22. The users swear their passwords are right, and half of them don't even type one. A forum post says to tick Ignore user account dial-in properties, add a policy that accepts users without validating credentials until it's sorted, and reissue the NPS certificate. Can we start with that?"
Not yet. Event 6273 doesn't mean NPS is broken. It means NPS received the request, ran it through its policies, and refused it, and the event itself records which policy, which EAP type, and which reason. Microsoft's Event 6273 message is "Network Policy Server denied access to a user." Reason code 16 is "Authentication failed due to a user credentials mismatch. Either the user name provided does not match an existing user account or the password was incorrect." Reason code 22 is "Network Policy Server was unable to negotiate the use of an Extensible Authentication Protocol (EAP) type with the client computer." Neither one says the password was wrong for certain. Reason 16 also shows up when a certificate can't be mapped to an account, and reason 22 shows up when the client and the policy never agreed on a method, often because of the NPS server's own certificate (our reading, Steps 4 and 6). Ignoring dial-in properties doesn't touch either of those, and an accept-without-credentials policy opens the network to everyone. Work through it as a chain: which network, which users or devices, since when → is NPS auditing on, and is it 6273 or something else? → read one 6273 end to end (policy names, authentication type, EAP type, account, reason) → reason 22: did the client and the policy agree on an EAP type, and is the NPS server certificate valid and bound? → reason 16 with passwords: is the account real, unlocked, and reachable on a DC? → reason 16 with certificates: does the certificate map to the account (strong mapping since February 2025)? → does the request reach the policy you think it does? → is the NPS server itself registered, logging, and healthy? auditpol, Get-WinEvent, the NPS accounting log, Get-ADUser, the certificate store, and certutil are the sources for that chain. Accept everyone and you'll be finding out later which devices got on while it was open.
If the Wi-Fi or VPN profile never reached the device, Intune Wi-Fi Profile Not Applying starts earlier in the chain. If the rejections began when a CRL expired or a CA changed, Revocation Server Was Offline reads the chain first. This post covers "NPS (Network Policy Server) on Windows Server rejects 802.1X Wi-Fi, wired 802.1X, or VPN connections with Event 6273 and reason code 16 or 22, and you need a read-first path before you loosen policies, accept unauthenticated users, roll back security updates, or reissue every certificate."
TL;DR
- The event names the policy that rejected the request. Microsoft's 802.1X guide: "NPS event log entries contain information about the connection attempt, including the name of the connection request policy that matched the connection attempt and the network policy that accepted or rejected the connection attempt." (Step 3).
- Password or certificate decides which reason-16 path you take. Microsoft's 6273 page: "Use the information provided in Event Viewer to determine whether the authentication method that applies to the user connection is password- or certificate-based." (Steps 5 and 6).
- Reason 22 is often the NPS server certificate. Microsoft: "In Network Policy Server (NPS) on Windows Server, the server certificate that you bind to a network policy isn't updated automatically when it expires." (Step 4).
- Certificate users rejected since early 2025 need a strong mapping. Microsoft's KB5014754 on Full Enforcement mode: "Authentication will be denied if a certificate cannot be strongly mapped." (Step 6).
- Policies are an ordered list. Microsoft: "NPS checks each connection request against the first rule in the list, then the second, and so on, until a match is found." (Step 7).
- Certificates are the usual 802.1X break. Microsoft: "Most 802.1X authentication issues are because of problems with the certificate that's used for client or server authentication." (Steps 4, 6, 9).
Where in the chain did it break?
| Step | What should be true | Typical symptom when it breaks |
|---|---|---|
| 1. Symptom captured | Which network, which NAS, which users or devices, since when | "The Wi-Fi is broken" with no event |
| 2. Auditing and events | NPS auditing on; the failure is a 6273, not 13, 18, or 6274 | No events at all, or the wrong event |
| 3. One 6273 read | Policy names, authentication type, EAP type, account, reason known | Reason code read, nothing else |
| 4. EAP type agreed (22) | Client and policy offer the same method; NPS server certificate valid and bound | PEAP on clients, EAP-TLS only in the policy, or an expired NPS certificate |
| 5. Password account (16) | Account exists, is enabled, unlocked, and a DC can check it | Locked account, stale saved password, wrong domain |
| 6. Certificate account (16) | Client certificate valid, right EKU and SAN, strongly mapped | Certificates issued before strong mapping, rejected since the DC update |
| 7. Policy match | The intended connection request and network policy match first | An older, broader policy higher in the list |
| 8. NPS server | Registered in AD, logging works, service and extensions healthy | NPS not in RAS and IAS Servers, log disk full, MFA extension rejecting |
| 9. Other reason codes | You know what the code in front of you means | 16 and 22 fixes applied to a 265 or a 48 |
| 10. Change | Only after Steps 1-9 agree: one link, one change | Accept-everyone policy, same broken mapping |
Step 1: Capture the symptom (read-only)
Write these on the ticket first:
| Fact | Why it matters |
|---|---|
| Which network | One SSID, one wired switch, or the VPN points at one NAS and its RADIUS client entry in NPS |
| Which users or devices, and how many | One user is an account; every user on one method is the policy, the certificate, or the server |
| User or computer authentication | Wi-Fi often authenticates the computer first; the event's account name shows which (Step 3) |
| Which method you expect | PEAP-MS-CHAP v2 (password), PEAP-TLS or EAP-TLS (certificate) |
| Which NPS servers | Two NPS servers behind one SSID can have different certificates and policies |
| Since when, and what changed | Patch night on DCs or NPS, NPS certificate renewal, new CA, Windows 11 upgrade, Intune profile change, new switch or controller |
Then branch on what you see:
| What you see | What it usually means (our reading unless noted) | Start at |
|---|---|---|
| Reason 16 for everyone on certificate authentication since DC patching | Certificates without a strong mapping, now enforced | Step 6 |
| Reason 16 for a few users on PEAP-MS-CHAP v2 | Wrong or stale password, locked or disabled account | Step 5 |
| Reason 16 for computer accounts (host/...) | Machine password or account problem on those devices | Step 5 |
| Reason 22 for every client since a certain date | NPS server certificate expired or replaced, or a policy method changed | Step 4 |
| Reason 22 for one device type (Macs, phones, a new image) | That client offers a method or TLS version the policy doesn't | Step 4 |
| Password prompts on Windows 11 after an upgrade, then 16 or 22 | Credential Guard blocking saved MS-CHAP v2 sign-in | Step 5 |
| No 6273 at all, users still fail | Request never reached NPS, or auditing is off | Step 2 |
| A different reason code | Look it up first | Step 9 |
Step 2: Confirm auditing, then find the events (read-only)
Microsoft's NPS troubleshooting checklist starts with the audit policy:
:: Read-only. On each NPS server: is the Network Policy Server audit subcategory on? auditpol /get /subcategory:"Network Policy Server" Microsoft says auditing is on when that shows Success and Failure, or Failure. If it shows No Auditing, the fix is Microsoft's auditpol /set line in Step 10, and Microsoft adds: "Even if audit policy appears to be fully enabled, it sometimes helps to disable and then re-enable this setting." Microsoft's audit page notes "This subcategory generates events only if NAS or IAS role is installed on the server."
The events live in the Security log on the NPS server, from Microsoft-Windows-Security-Auditing (Microsoft's 6273 event details). Microsoft's checklist: "Check for events that have Event ID 6273 or 6274. Most authentication failures produce these events." And: "Check the reason codes of the authentication failure events. The reason code indicates the cause of the failure."
# Read-only. On the NPS server: the last 24 hours of NPS denials, grouped by reason code, policy, and EAP type # (field labels from Microsoft's 6273 event template; the regex parsing is ours) $since = (Get-Date).AddHours(-24) $denied = Get-WinEvent -FilterHashtable @{ LogName = 'Security'; Id = 6273; StartTime = $since } -ErrorAction SilentlyContinue | ForEach-Object { $m = $_.Message [pscustomobject]@{ Time = $_.TimeCreated Account = if ($m -match 'Account Name:\s+(.+)') { $Matches[1].Trim() } NetworkPolicy = if ($m -match 'Network Policy Name:\s+(.+)') { $Matches[1].Trim() } ProxyPolicy = if ($m -match 'Proxy Policy Name:\s+(.+)') { $Matches[1].Trim() } AuthType = if ($m -match 'Authentication Type:\s+(.+)') { $Matches[1].Trim() } EapType = if ($m -match 'EAP Type:\s+(.+)') { $Matches[1].Trim() } RadiusClient = if ($m -match 'Client Friendly Name:\s+(.+)') { $Matches[1].Trim() } ReasonCode = if ($m -match 'Reason Code:\s+(\d+)') { [int]$Matches[1] } } } $denied | Group-Object ReasonCode, NetworkPolicy, EapType -NoElement | Sort-Object Count -Descending | Format-Table -AutoSize Account Name appears twice in the event (user and client machine); the first match is the user section (our reading of Microsoft's template). If one reason and one policy dominate, that's your chain. If the codes are spread out, take one user at a time.
The neighbors of 6273, each from Microsoft's audit page or NPS troubleshooting guidance:
| Event | Microsoft's text | What it tells you (our reading unless noted) |
|---|---|---|
| 6272 | "Network Policy Server granted access to a user." | The success to compare against (Step 10) |
| 6273 | "Network Policy Server denied access to a user." | This post |
| 6274 | "Network Policy Server discarded the request for a user." | Microsoft lists it with 6273 for most failures; read its reason code the same way |
| 6279 | "Network Policy Server locked the user account due to repeated failed authentication attempts." | NPS's own remote access lockout (reason 64, Step 9) |
| 13 | A RADIUS message from an invalid RADIUS client IP | Microsoft: "The NPS event log records this event when the NPS server receives a message from a radius client that isn't on the configured list of radius clients." No 6273 is written for those |
| 18 | Message authenticator not valid | Microsoft: "The NPS event log records this event when authentication fails because the shared secret key of the radius client doesn't match the shared secret key of the NPS server." |
Events 13 and 18 are in the System log (Microsoft's NPS troubleshooting guidance lists them as NPS events; the log is our reading). If neither 6273 nor 13 nor 18 appears while users fail, the request may not be reaching this server. Microsoft: "By default, NPS sends and receives RADIUS traffic by using User Datagram Protocol (UDP) ports 1812, 1813, 1645, and 1646."
# Read-only. On the NPS server: is NPS listening on the RADIUS ports, and which NPS servers does the NAS point at? Get-NetUDPEndpoint -LocalPort 1812, 1813, 1645, 1646 -ErrorAction SilentlyContinue | Select-Object LocalAddress, LocalPort, OwningProcess Get-NpsRadiusClient | Select-Object Name, Address, Enabled Get-NpsRadiusClient "gets Remote Authentication Dial-In User Service (RADIUS) clients." Check that the access point, controller, switch, or VPN server sending the request is in the list with the address it actually uses (Microsoft's checklist item: "The RADIUS Clients and Servers list includes the radius client in question.").
Step 3: Read one 6273 end to end (read-only)
The reason code is one field out of more than twenty. Microsoft's 802.1X guide: "In the event message, scroll to the bottom, and then check the Reason Code field and the text that's associated with it." Read the rest of the event first, for one user who is failing right now:
# Read-only. On the NPS server: the newest 6273 for one account (the name is an example), full message Get-WinEvent -FilterHashtable @{ LogName = 'Security'; Id = 6273 } -MaxEvents 500 | Where-Object { $_.Message -match 'jdoe' } | Select-Object -First 1 -Property TimeCreated, Message | Format-List The fields, in the order Microsoft's event template lists them, and what each one decides:
| Section and field | What to read (our reading unless noted) |
|---|---|
| User: Account Name, Account Domain | A DOMAIN\user or UPN is a user logon; a host/ name is the computer authenticating (Step 5). A blank or odd domain points at the client's identity setting |
| Client Machine: Calling Station Identifier | Microsoft: "In 802.1x authentications the MAC Address is typically populated and can be matched from the client." It ties the event to one device |
| NAS: NAS IPv4 Address, NAS Identifier, NAS Port-Type | Which access point, switch, or VPN server sent it, and the media type the policy's NAS Port Type condition compares |
| RADIUS Client: Client Friendly Name, Client IP Address | The RADIUS client entry that matched (Step 2) |
| Authentication Details: Proxy Policy Name | The connection request policy that matched (Step 7) |
| Authentication Details: Network Policy Name | The network policy that rejected it. Not the one you expected means Step 7 first |
| Authentication Details: Authentication Type, EAP Type | What the client actually used: PEAP or EAP, and the inner type. Compare with Step 4 |
| Authentication Details: Authentication Server | Which server did the authentication: this NPS, or a remote RADIUS server if the request was forwarded (Step 7) |
| Reason Code, Reason | Read last, with the fields above already known |
Two things trip people up here. The reason text in current events can differ from Microsoft's 2008-era reason-code table: a 2024 Microsoft Q&A post quotes the reason 22 text as "The client could not be authenticated because the Extensible Authentication Protocol (EAP) Type cannot be processed by the server." Same code, same meaning. And a 6273 that names an unexpected network policy is a policy-order problem before it's a credential problem, whatever the code says (our reading).
Then the accounting log, which records every request and response, not only failures. Microsoft's Always On VPN guide: "NPS creates and stores the NPS accounting logs." Microsoft's accounting page: "The default location is the systemroot\System32\LogFiles folder." The file names start with IN (Microsoft's Always On VPN page shows the naming).
# Read-only. On the NPS server: the newest accounting log files, then every line for one account $logs = Get-ChildItem -Path "$env:windir\System32\LogFiles" -Filter 'IN*' | Sort-Object LastWriteTime | Select-Object -Last 2 $logs | Select-Object Name, Length, LastWriteTime $logs | Select-String -Pattern 'jdoe' | Select-Object -Last 20 | ForEach-Object { $_.Line } Microsoft's Always On VPN page lists the database-format fields, including Packet-Type, User-Name, Calling-Station-ID, NAS-IP-Address, Client-Friendly-Name, Authentication-Type, Policy-Name, and Reason-Code. If your server writes the DTS Compliant (XML) format, the same names appear as elements (our reading of Microsoft's accounting page). Microsoft on the log: "The NPS logs can help you diagnose policy-related issues." A request with no response line at all, or nothing in the log for that user, sends you back to Step 2 (our reading).
Step 4: For reason 22, did the client and the policy agree on an EAP type? (read-only)
Reason 22 means the EAP conversation never got as far as the account. Three things decide it: which method the client offers, which methods the matching policy allows, and whether the NPS server can present a usable certificate for that method (our reading of Microsoft's reason-code and certificate pages).
The policy side. Microsoft's checklist item: "The network policy constraints list the correct authentication method." In the NPS console that's the policy's Constraints tab, Authentication Methods, EAP Types. A Microsoft-moderated answer on a 2018 reason 22 thread (community): "Please make sure you have selected PEAP-MSCHAPv2; not MSCHAPv2 as a supported authentication method in your NPS policy." Microsoft's Always On VPN page describes the same mismatch from the client side, for error 812: "You typically encounter this error when the NPS specified an authentication condition the client can't meet."
The client side. On a failing Windows client, the WLAN or Wired AutoConfig log shows the method and the reason Windows gave up. Microsoft: "On the client side, go to Event Viewer (Local)\Applications and Services Logs\Microsoft\Windows\WLAN-AutoConfig/Operational for wireless issues."
# Read-only. On a failing Windows client: the newest WLAN AutoConfig events (wired: Microsoft-Windows-Wired-AutoConfig/Operational) Get-WinEvent -LogName 'Microsoft-Windows-WLAN-AutoConfig/Operational' -MaxEvents 30 | Select-Object TimeCreated, Id, LevelDisplayName, Message | Format-List Read the EAP method the client used and compare it with the 6273's Authentication Type and EAP Type and the policy's list. PEAP on the client with only "Smart card or other certificate" in the policy, or EAP-TLS on the client with only PEAP in the policy, is a reason 22 by design (our reading). Microsoft also warns not to offer the same inner method both tunneled and untunneled: "When you deploy both a tunneled EAP method and EAP (which isn't protected), don't use the same authentication type."
The NPS server certificate. PEAP-MS-CHAP v2 needs one too. Microsoft: "With PEAP-MS-CHAP v2, PEAP-TLS, or EAP-TLS as the authentication method, the NPS must use a server certificate that meets the minimum server certificate requirements." And the part that breaks things on renewal day: "When the certificate applied to a policy expires, an administrator must manually update each policy that uses certificate-based authentication to reference a new, non-expired certificate. Until you update the policy, clients that rely on that policy can't successfully authenticate." Microsoft adds that this manual step "isn't required on NPS servers configured for certificate autoenrollment."
Microsoft publishes a read-only way to see which certificate a policy is bound to: export the configuration and pull the thumbprint from the policy's EAP blob. Microsoft's snippet, with the policy name as the only change:
# Read-only (writes one XML file). On the NPS server: which certificate thumbprint is bound to this network policy? # Microsoft's snippet from "Manage certificates used with NPS"; the export contains RADIUS shared secrets in clear text, so delete it after reading $PolicyName = "CORP-SECURE Wireless" # Change this to your policy name (case-insensitive) $NPSConfigPath = "$env:TEMP\nps-config.xml" Export-NpsConfiguration -Path $NPSConfigPath $blob = (([xml](Get-Content "$env:TEMP\nps-config.xml" -Raw)).SelectNodes("//RadiusProfiles//*[@name]") | Where-Object { $_.name -ieq $PolicyName }).Properties.msEAPConfiguration.'#text' $found = [regex]::Matches($blob, '14000000([0-9a-f]{40})') | ForEach-Object { $_.Groups[1].Value.ToUpper() } | Select-Object -Unique if (-not $found) { "No certificate thumbprint found in policy '$PolicyName'" } elseif ($found.Count -eq 1) { "Bound certificate thumbprint:$found" } else { "WARNING: multiple candidate thumbprints found, manual review of $NPSConfigPath needed:`n$($found -join "`n")" } Microsoft's caution on that file: "The exported NPS configuration file contains unencrypted shared secrets for RADIUS clients and members of remote RADIUS server groups." Then compare the thumbprint with what's actually in the machine store:
# Read-only. On the NPS server: certificates that can do server authentication, with expiry and names Get-ChildItem -Path Cert:\LocalMachine\My -SSLServerAuthentication | Select-Object Thumbprint, Subject, NotAfter, @{ n = 'DnsNames'; e = { $_.DnsNameList -join ', ' } }, @{ n = 'EKU'; e = { $_.EnhancedKeyUsageList.FriendlyName -join ', ' } } | Format-List # Anything expiring in the next 30 days Get-ChildItem -Path Cert:\LocalMachine\My -ExpiringInDays 30 | Select-Object Thumbprint, Subject, NotAfter The bound thumbprint missing from that list, or present with a past NotAfter, is your reason 22. Microsoft's server certificate requirements, each checkable in that output: "The Subject name contains a value."; the certificate includes "the Server Authentication purpose in EKU extensions (the object identifier (OID) for Server Authentication is 1.3.6.1.5.5.7.3.1)"; "The Subject Alternative Name (SubjectAltName) extension, if used, must contain the DNS name of the server." And it has to be trusted by the clients: it must "Be issued by a certification authority (CA) that is trusted by client computers." A new certificate from a different CA, or a client profile that pins the old server name or root, fails here even though the certificate itself is fine (our reading of Microsoft's client-side validation rules: "The name in the Subject line of the server certificate matches the name that's configured on the client for the connection.").
TLS settings. In the same 2018 thread, the poster found the cause in a hardening change: "I followed a document from microsoft increasing security by turning off SSL 2.0/3.0 and TLS 1.0/1.1 and only allowing TLS 1.2." That was Windows Server 2012 (community, old). On current builds, don't re-enable old protocols on that basis; read what changed under SCHANNEL and when, and compare with a server that works (our reading):
:: Read-only. On the NPS server: SCHANNEL protocol overrides (no output under Protocols = OS defaults) reg query "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols" /s Clocks matter at this step too: reason 264 is "The Security Support Provider Interface (SSPI) called by EAP reports that the system clocks on the NPS server and the access client are not synchronized." See Windows Time Not Syncing With Domain Controller for that read.
Step 5: For reason 16 with passwords, is the account real, usable, and reachable? (read-only)
This step is for PEAP-MS-CHAP v2 (the event's EAP Type says so). Microsoft's NPS troubleshooting page lists three checks for 6273 reason 16: "Check that the username and password for the user are valid.", "Check to see whether the user account is locked in Active Directory.", and "Check that the request is targeted to the correct domain controller and that the user account exists."
# Read-only. Any domain-joined machine with RSAT: the account NPS was asked about (the name is an example) Get-ADUser -Identity jdoe -Properties Enabled, LockedOut, PasswordExpired, PasswordLastSet, BadLogonCount, LastBadPasswordAttempt, AccountExpirationDate, UserPrincipalName | Select-Object SamAccountName, UserPrincipalName, Enabled, LockedOut, PasswordExpired, PasswordLastSet, BadLogonCount, LastBadPasswordAttempt, AccountExpirationDate BadLogonCount and LastBadPasswordAttempt come from the DC that answered, so read them on the DC that NPS uses (our reading). Disabled, expired, and locked accounts usually get their own codes (34, 35, 36), so a reason 16 with a healthy-looking account points at the password the client sent or the name it sent it under (our reading of Microsoft's reason-code table).
The DC's side of the same attempt. MS-CHAP v2 is validated by the DC, so the DC's Security log should show the attempt as Event 4776 (our reading; Microsoft: "This event generates every time that a credential validation occurs using NTLM authentication." and "For domain accounts, the domain controller is authoritative.").
# Read-only. On a DC (or remotely with -ComputerName): recent 4776 entries for the account Get-WinEvent -ComputerName DC01 -FilterHashtable @{ LogName = 'Security'; Id = 4776; StartTime = (Get-Date).AddHours(-4) } -MaxEvents 2000 |...