How to Configure NPS for 802.1X Authentication on Windows Server 2012 R2
Network Policy Server (NPS) is the Microsoft implementation of RADIUS (Remote Authentication Dial-In User Service) on Windows Server 2012 R2. When combined with 802.1X-capable network switches and wireless access points, NPS enables port-based network access control: devices can only connect to the network after authenticating their identity using AD credentials, computer certificates, or smart cards. This prevents unauthorized devices from gaining network access, enforces network segmentation via VLAN assignment, and provides centralized authentication logging. This guide covers deploying NPS for both wired 802.1X (EAP-TLS with machine certificates) and wireless authentication.
Prerequisites
– Windows Server 2012 R2 for the NPS server
– Active Directory domain with at least one Domain Controller
– 802.1X-capable network switches (Cisco, HP, etc.) or wireless access points
– An Enterprise CA with computer certificate templates for EAP-TLS
– NPS server certificate (for PEAP, issued by enterprise CA)
– Active Directory groups for network access policy (e.g., CorpNetworkAccess)
– Network reachability from switches/APs to NPS server on UDP 1812 (authentication) and 1813 (accounting)
Step 1: Install Network Policy Server
# Install NPS role
Install-WindowsFeature -Name NPAS -IncludeManagementTools
# Import the NPS module
Import-Module NetworkPolicyServer
# Register NPS in Active Directory (required for reading computer and user objects)
netsh nps add registeredserver domain=corp.local server=nps01.corp.local
# Or via command:
Register-NpsServer -Domain corp.local
# Verify registration
Get-ADGroupMember -Identity "RAS and IAS Servers" |
Select-Object Name | Format-Table -AutoSize
# NPS server should appear in "RAS and IAS Servers" group
# Start the NPS service
Start-Service IAS
Set-Service IAS -StartupType Automatic
Get-Service IAS | Select-Object Status, StartType
Step 2: Obtain an NPS Server Certificate
For PEAP-MSCHAPv2 (most common for wireless), the NPS server needs a server authentication certificate that clients trust. For EAP-TLS, both client and server need certificates:
# Request a server authentication certificate for NPS
# The certificate needs "Server Authentication" EKU (1.3.6.1.5.5.7.3.1)
# Auto-enrollment will handle this if the computer certificate template includes Server Authentication
# Trigger auto-enrollment on the NPS server
gpupdate /force
certutil -pulse
# Verify NPS server has a valid server certificate
Get-ChildItem Cert:LocalMachineMy |
Where-Object {
$_.EnhancedKeyUsageList.FriendlyName -contains "Server Authentication" -and
$_.Issuer -like "*Corp-Issuing*"
} |
Select-Object Subject, NotAfter, Thumbprint | Format-Table -AutoSize
# If no cert, manually request one
certreq -new "C:NPSServerAuth.inf" "C:NPSServerAuth.csr"
certreq -submit -config "corp-issuing-ca-01.corp.localCorp-Issuing-CA-01" "C:NPSServerAuth.csr" "C:NPSServerAuth.cer"
certreq -accept "C:NPSServerAuth.cer"
Step 3: Add RADIUS Clients (Switches and Access Points)
Import-Module NetworkPolicyServer
# Add RADIUS clients for each switch and access point
# Each network device needs a unique shared secret
# Generate a strong shared secret
function New-SharedSecret {
param([int]$Length = 32)
$chars = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789!@#$%"
return -join (1..$Length | ForEach-Object { $chars[(Get-Random -Maximum $chars.Length)] })
}
$switches = @(
@{Name="CoreSwitch01"; Address="10.10.1.1"},
@{Name="CoreSwitch02"; Address="10.10.1.2"},
@{Name="AccessSwitch-Floor1"; Address="10.10.2.1"},
@{Name="AccessSwitch-Floor2"; Address="10.10.2.2"},
@{Name="WiFi-AP-Controller"; Address="10.10.5.1"}
)
$secretLog = [System.Collections.Generic.List[PSCustomObject]]::new()
foreach ($device in $switches) {
$secret = New-SharedSecret -Length 32
New-NpsRadiusClient `
-Name $device.Name `
-Address $device.Address `
-AuthAttributeRequired $false `
-SharedSecret $secret `
-VendorName "RADIUS Standard" # Or "Cisco Systems" for Cisco devices
$secretLog.Add([PSCustomObject]@{
Device = $device.Name
Address = $device.Address
Secret = $secret # Save this — configure the same secret on each device
})
Write-Host "Added RADIUS client: $($device.Name)" -ForegroundColor Green
}
# Export secrets for network team (store securely!)
$secretLog | Export-Csv "C:NPSRADIUSClientSecrets_$(Get-Date -f yyyyMMdd).csv" -NoTypeInformation
Write-Host "RADIUS client secrets exported. Distribute to network team securely."
# Verify clients
Get-NpsRadiusClient | Select-Object Name, Address, Enabled | Format-Table -AutoSize
Step 4: Create Connection Request Policy
Connection Request Policies determine how NPS handles RADIUS requests — whether to authenticate them locally or forward them to another RADIUS server:
Import-Module NetworkPolicyServer
# Create a Connection Request Policy for wired 802.1X
New-NpsNetworkPolicy `
-Name "Wired 802.1X EAP-TLS" `
-ProcessingOrder 10 `
-PolicySource NAP `
-Enabled $true
# The NPS GUI (nps.msc) provides a more complete wizard for connection request policies
# Key settings:
# - Policy Name: "Corporate 802.1X"
# - Conditions: NAS-Port-Type = Ethernet (15) for wired
# - Conditions: NAS-Port-Type = Wireless-IEEE-802.11 (19) for wireless
# - Authentication: This server (local NPS authentication)
# - Attributes: Forward all request attributes
# For complex configurations, use netsh NPS or the NPS GUI wizard
netsh nps add crp name="Corporate 802.1X Access" `
state=enable processingorder=1 `
policysource=0
Step 5: Create Network Policy for EAP-TLS (Machine Certificates)
# Create the Network Policy for EAP-TLS authentication
# EAP-TLS uses mutual certificate authentication (strongest option)
# Via netsh (command-line configuration)
netsh nps add np name="Domain Computers - EAP-TLS" `
state=enable processingorder=10
# The policy must be configured in the NPS MMC for full EAP settings
# Key Network Policy settings:
# Name: "Domain Computers - EAP-TLS"
# Processing Order: 10
# Policy Status: Enabled
#
# Conditions:
# - Windows Groups: CORPDomain Computers
# - NAS-Port-Type: Ethernet
#
# Constraints:
# - Authentication Methods: EAP (Enabled)
# - Microsoft: Smart Card or other certificate
# - Server certificate:
#
# Settings:
# - Standard RADIUS Attributes:
# - Service-Type: Framed
# - Framed-Protocol: PPP
# - Vendor Specific (for VLAN assignment):
# - Tunnel-Type: VLAN (13)
# - Tunnel-Medium-Type: IEEE-802 (6)
# - Tunnel-Pvt-Group-ID:
# Export NPS configuration for documentation
Export-NpsConfiguration -Path "C:NPSNPSConfig_$(Get-Date -f yyyyMMdd).xml"
Step 6: Create Network Policy for PEAP-MSCHAPv2 (Wireless Users)
# PEAP-MSCHAPv2 is the most common wireless authentication method
# It authenticates users with AD credentials (username/password) over a TLS tunnel
# Configure via nps.msc wizard — key settings:
# Network Policy Name: "Wireless Users - PEAP"
# Processing Order: 20
# Conditions:
# - Windows Groups: CORPDomain Users
# - NAS-Port-Type: Wireless-IEEE-802.11
#
# Authentication Method:
# - Protected EAP (PEAP)
# - Server Certificate:
# - Inner Method: EAP-MSCHAPv2
# - Enable Fast Reconnect
#
# VLAN Assignment (put wireless clients in a separate VLAN):
# - Tunnel-Type: VLAN (13)
# - Tunnel-Medium-Type: IEEE-802 (6)
# - Tunnel-Pvt-Group-ID: "200" # Wireless VLAN
# Using netsh to configure PEAP (partial — full config via MMC):
netsh nps set np name="Wireless Users - PEAP" `
state=enable processingorder=20
Write-Host "Configure PEAP authentication settings via nps.msc"
Step 7: Configure Switch for 802.1X (Cisco IOS Example)
# The following configuration is for a Cisco IOS switch
# Configure this on each managed access switch
# Global AAA configuration
aaa new-model
aaa authentication dot1x default group radius
aaa authorization network default group radius
aaa accounting dot1x default start-stop group radius
# RADIUS server configuration
radius server NPS01
address ipv4 10.10.0.50 auth-port 1812 acct-port 1813
key YOUR_SHARED_SECRET_HERE
!
radius server NPS02
address ipv4 10.10.0.51 auth-port 1812 acct-port 1813
key YOUR_SHARED_SECRET_HERE
# Enable 802.1X globally
dot1x system-auth-control
# Configure per-interface (access port)
interface GigabitEthernet1/0/1
description Workstation Port
switchport mode access
switchport access vlan 100
authentication port-control auto
authentication event fail action authorize vlan 999
authentication event server dead action authorize vlan 999
dot1x pae authenticator
spanning-tree portfast
!
# Dynamic VLAN assignment (NPS sends VLAN ID via RADIUS attributes)
# Ensure RADIUS attributes in NPS policy include:
# Tunnel-Type = VLAN (13)
# Tunnel-Medium-Type = 802 (6)
# Tunnel-Private-Group-ID = "100" (VLAN number as string)
Step 8: Configure NPS Logging and Accounting
Import-Module NetworkPolicyServer
# Configure SQL Server logging (for persistent audit trail)
# Or use flat file logging:
$logPath = "C:NPSLogs"
New-Item -ItemType Directory -Path $logPath -Force
# Configure NPS to log to a file
Set-NpsLogFileFormat `
-Format ODBC `
-LogArtificialAttributesEnabled $true
# Configure file-based accounting log
# Via netsh:
netsh nps set accounting logfile state=enable format=DTS `
accountingtype=requests logperiod=daily dir="$logPath"
# Read NPS event logs for authentication events
# NPS authentication events are in the Security log (Event ID 6272-6280)
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = @(6272, 6273, 6274, 6275, 6276, 6277, 6278, 6279, 6280)
StartTime = (Get-Date).AddHours(-1)
} | Select-Object TimeCreated, Id, Message | Format-Table -Wrap
# Event meanings:
# 6272 = Network Policy Server granted access to a user
# 6273 = Network Policy Server denied access to a user
# 6274 = Network Policy Server discarded the request
# 6280 = Network Policy Server unlocked the user account
Verification
# Full NPS verification
Write-Host "=== NPS Health Check ===" -ForegroundColor Cyan
# Service status
Get-Service IAS | Select-Object Status, StartType
# RADIUS clients
$clients = Get-NpsRadiusClient
Write-Host "RADIUS Clients: $($clients.Count)"
$clients | Select-Object Name, Address, Enabled | Format-Table -AutoSize
# Server certificate for PEAP
$npsCert = Get-ChildItem Cert:LocalMachineMy |
Where-Object {
$_.EnhancedKeyUsageList.FriendlyName -contains "Server Authentication" -and
$_.Issuer -like "*Corp-Issuing*"
}
if ($npsCert) {
Write-Host "NPS Server Cert: $($npsCert.Subject) (expires $($npsCert.NotAfter))" -ForegroundColor Green
} else {
Write-Host "NPS Server Cert: NOT FOUND" -ForegroundColor Red
}
# NPS registration in AD
$rrasGroup = Get-ADGroupMember "RAS and IAS Servers"
if ($rrasGroup.Name -contains $env:COMPUTERNAME) {
Write-Host "AD Registration: OK" -ForegroundColor Green
} else {
Write-Host "AD Registration: NOT REGISTERED" -ForegroundColor Red
}
# Test RADIUS connectivity
netsh nps show status
Summary
Configuring NPS for 802.1X on Windows Server 2012 R2 creates a robust network access control system that authenticates every device and user before granting network access. By installing and registering NPS in Active Directory, adding all switches and access points as RADIUS clients with unique shared secrets, creating network policies for EAP-TLS (certificate-based machine authentication) and PEAP-MSCHAPv2 (credential-based user authentication), configuring switches for 802.1X port control with dynamic VLAN assignment, and enabling comprehensive logging, you prevent unauthorized devices from joining the corporate network. This is the foundation for a zero-trust network architecture where every connection is authenticated and network segments are enforced by policy rather than physical topology.