Windows Server  ·  high  ·  Exchange, WSUS, PKI & RDS

802.1X or VPN authentication fails at NPS — reason codes 16, 23, 48 and 265

NPS logs a numeric reason for every rejection, and that number is the diagnosis.

What you see

Wi-Fi or VPN authentication fails for some or all users. The client gives a generic message; the server has the detail.

What is actually wrong

Reason 265 is a certificate chain problem, 48 means no policy matched, 16 is bad credentials, and 23 is an authentication protocol mismatch.

Codes and articles

Event 6273Reason Code 265Reason Code 48Reason Code 16Reason Code 23NPSRADIUS

Fixes (3)

Fix the certificate chain
Elevated PowerShell on the NPS server40 minutesmedium riskreversible

Reason code 265.

  1. Read the rejection, which names the certificate problem.

    PowerShell
    Get-WinEvent -LogName Security -MaxEvents 100 | Where-Object Id -eq 6273 | Select-Object -First 3 | Format-List Message
  2. Check the server certificate NPS is using — it needs a Server Authentication EKU and the private key.

    PowerShell
    Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.EnhancedKeyUsageList.FriendlyName -contains 'Server Authentication' } | Format-List Subject,NotAfter,Thumbprint,HasPrivateKey
  3. The most common cause is an expired certificate that was renewed but not selected in the network policy. Renewing does not update the policy.

    The policy stores the certificate by identity. A renewed certificate is a new object, so the policy still points at the old one and every authentication fails on the day it expires.

  4. Open the network policy, edit the PEAP or EAP-TLS configuration, and select the current certificate. Do this on every NPS server.

  5. Confirm the clients trust the issuing CA — if they do not, they reject the server and it presents at the server as this code.

    PowerShell
    Get-ChildItem Cert:\LocalMachine\Root | Where-Object Subject -like '*YourCA*' | Format-List Subject,NotAfter
  6. Check the CRL is reachable from the clients, since a revocation check that cannot complete fails closed by default.

    PowerShell
    certutil -URL (Get-ChildItem Cert:\LocalMachine\My | Select-Object -First 1).Thumbprint
Confirm it workedEvent 6272 (access granted) appears and clients authenticate.
PowerShell
Get-WinEvent -LogName Security -MaxEvents 50 | Where-Object Id -eq 6272 | Select-Object -First 3 TimeCreated
If you need to undo itThe previous certificate can be reselected in the policy if it has not expired.
Get a policy to match
Elevated PowerShell35 minutesmedium riskreversible

Reason code 48.

  1. Read the event — it lists the conditions that were evaluated.

    PowerShell
    Get-WinEvent -LogName Security -MaxEvents 50 | Where-Object Id -eq 6273 | Select-Object -First 2 | Format-List Message
  2. List the policies and their order. They are evaluated top to bottom and the first match wins.

    PowerShell
    Get-NpsNetworkPolicy | Format-Table PolicyName,Enabled,ProcessingOrder,PolicySource -AutoSize

    A disabled policy or one below a broader deny rule is the usual cause. The order matters as much as the contents, and the console makes it easy to add a correct policy in the wrong position.

  3. Check the connection request policy too — that is evaluated first and can reject before the network policy is reached.

    PowerShell
    Get-NpsRadiusClient | Format-Table Name,Address,Enabled
  4. Check the RADIUS client is registered with the right shared secret — an unregistered access point is silently ignored.

  5. Verify the user or computer is in the group the policy requires.

    PowerShell
    Get-ADUser jbloggs -Properties MemberOf | Select-Object -ExpandProperty MemberOf
  6. Enable NPS accounting to a text file so failures are easier to read than in the Security log.

    PowerShell
    Get-NpsRadiusClient | Format-List
Confirm it workedThe connection matches the intended policy, named in event 6272.
If you need to undo itPolicy order and membership changes are reversible in the NPS console.
Resolve the authentication method or credential
Elevated PowerShell30 minutesmedium riskreversible

Reason 16 or 23.

  1. Reason 16 is a bad credential. Check the account is not locked or expired before assuming a policy fault.

    PowerShell
    Get-ADUser jbloggs -Properties LockedOut,PasswordExpired,Enabled,msNPAllowDialin | Format-List
  2. msNPAllowDialin set to False overrides everything else and is easy to miss.

    PowerShell
    Get-ADUser -Filter { msNPAllowDialin -eq $false } | Format-Table Name,SamAccountName

    The dial-in property on the user object takes precedence over the network policy. A single user failing while everyone else works is nearly always this.

  3. Reason 23 is a protocol mismatch. Compare what the policy permits against what the client offers.

    PowerShell
    Get-NpsNetworkPolicy | Format-List PolicyName,ProcessingOrder
  4. MS-CHAPv2 requires the account's password to be stored in a reversibly-compatible form for some methods — check the policy is not requiring something the directory cannot supply.

  5. For a machine-authenticating 802.1X deployment, confirm the computer account is being used rather than the user, and that the client is configured for computer authentication.

Confirm it workedThe account authenticates and event 6272 is logged.
If you need to undo itDirectory attribute changes should be recorded before altering them.

Where this stops. This write-up was written and checked by hand. It says what each step changes, how to confirm it worked and how to reverse it, and anything destructive is flagged before you reach it. If it does not match what your machine is doing, search the Support Centre for the exact code or message — and when something needs a person, get in touch.