entra-id
authentication
mfa
]
how to test NPS MFA using radclient
- Installing freeradius-utils
- Initial RADIUS testing with freeradius-utils
- Initial NPS MFA Adapter configuration
- MFA RADIUS testing with freeradius-utils
- NPS MFA Adapter migration considerations and reconfiguration during migration day
- Resources
In an Entra ID tenant-to-tenant migration project, we needed to test the behavior of Microsoft Network Policy Server (NPS), which was used as a RADIUS server to support MFA for VPN access. We wanted to:
- understand what it takes to change the NPS MFA adapter configuration,
- identify the key aspects of this change, and most importantly,
- test it thoroughly before deploying it in production on the day of migration (day-D).
In this post I’ll cover, how we approached this task. I’ll focus especially on:
- using freeradius-utils in Windows Subsystem for Linux (WSL) for testing NPS,
- NPS MFA Adapter configuration/migration aspects.
I’ll omit things such as installation and configuration of NPS and WSL. Ping me if you need further info, or check the resources at the bottom. NPS/MFA setup is pretty well documented.
Installing freeradius-utils
Installing radclient
is straight forward in Ubuntu (in my case, running in WSL).
Just execute:
sudo apt-get install freeradius-utils
Initial RADIUS testing with freeradius-utils
To test the NPS configuration, we need:
-
New radius client in your NPS server, generate a secret for the client and
-
Test NPS configuration with a test account using
radclient
command.
The first part is simple with NPS. It is illustrated by next picture.
To test using radclient
command, we need to setup our variables such as USERNAME
, PASSWORD
and shared SECRET
first:
# setup username, password and secret
# beware when copying / pasting into terminal as the commands
# perform a read operation :)
echo "Reading one-time settings"
read -e -p " Provide username: " USERNAME
read -s -e -p " Provide user password: " PASSWORD ; echo
read -s -e -p " Provide shared RADIUS secret: " SECRET ; echo
Next, we can test authentication:
CLIENTIP=`ip a s eth0 | grep -E -o 'inet [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d' ' -f2`
echo "Radius Client IP: $CLIENTIP"
echo "Trying to authenticate/authorize $USERNAME"
# authenticate with username/password
echo "User-Name=$USERNAME,User-Password=$PASSWORD,Framed-Protocol=PPP,NAS-IP-Address=$CLIENTIP" | /usr/bin/radclient -t 60 -x target.server.address:1812 auth "$SECRET"
If you are lucky enough, you’ll see Access-Accept
. This means access was granted.
If you are not so lucky, you’ll get Access-Reject
, you should
troubleshoot
the NPS then.
Initial NPS MFA Adapter configuration
Initial NPS MFA Adapter configuration is also simple:
- Download NpsExtnForAzureMfaInstaller.exe from Microsoft site.
- Run PowerShell script
AzureMfaNpsExtnConfigSetup.ps1
fromC:\Program Files\Microsoft\AzureMfa\Config
This script:
- Installs entire Microsoft.Graph PS module
- Asks for
tenantId
(or reads it from registry) - Generates self-signed certificate that is used for communication / authentication between NPS and the Entra ID tenant
- Grants necessary permissions on the endpoints called by NPS for authenticating/authorizing users via MFA
- Updates local configuration so that the new certificate is used in the NPS <=> Entra ID communications
- Grants permissions to the appropriate private key to
NETWORK SERVICE
- Restarts the NPS service (
ias
)
Typical output of the script is illustrated by next picture.
MFA RADIUS testing with freeradius-utils
Once the extension is installed and configured, the NPS server will call Entra ID for MFA for all NPS clients (e.g. VPN gateways) and by default will require MFA for all users.
If you do not have OTP authentication method enabled, the authenticator will
prompt you for approve sign-in request (without number matching). After
approval, you’ll receive an Access-Accept
or Access-Reject
response, just like
in previous testing scenarios.
On the other hand, if you have enabled OTP authentication method, you’ll need to authenticate “twice”:
- First, you authenticate with username and password, as in the first case.
The NPS server will respond with an
Access-Challenge
and providesState
parameter. - Second, you need to specify the
OTP
from the MS Authenticator app along with aState
challenge provided by the NPS server to complete the authentication.
Following snippet will help you with the testing via radclient
.
# authenticate with username/password,
# get the State parameter from response
STATE=`echo "User-Name=$USERNAME,User-Password=$PASSWORD,Framed-Protocol=PPP,NAS-IP-Address=$CLIENTIP" | /usr/bin/radclient -t 60 -x target.server.address:1812 auth "$SECRET" | grep State | cut -d = -f 2 | tr -d '[:blank:]'`
# read OTP from authenticator
read -e -p " Provide OTP from MS Authenticator: " OTP
# authenticate with OTP, pass the STATE
echo "User-Name=$USERNAME,User-Password=$OTP,State=$STATE,Framed-Protocol=PPP,NAS-IP-Address=$CLIENTIP" | /usr/bin/radclient -t 60 -x target.server.address:1812 auth "$SECRET"
And the testing is illustrated by next picture.
NPS MFA Adapter migration considerations and reconfiguration during migration day
The reconfiguration of the NPS MFA adapter is straightforward. You simply need
to rerun the PowerShell script AzureMfaNpsExtnConfigSetup.ps1
. During the
process, you’ll be prompted to select the new tenantId
. The rest of the
setup is simple and easy to follow.
WARNING
Though reconfiguring NPS is simple, be aware of unintended consequences. Previously, all of your users might have been enrolled in MFA. However, during tenant-to-tenant migrations, it’s common for users to enroll for MFA gradually. Fortunately, NPS supports requiring MFA authentication only for users who are already enrolled.
To take advantage of requiring MFA authentication only for users who are MFA enabled, you must reconfigure NPS server via registry.
reg add "HKLM\SOFTWARE\Microsoft\AzureMfa" /v "REQUIRE_USER_MATCH" /t REG_SZ /d "FALSE" /f
To revert the configuration either set the value to TRUE
or delete the registry setting.
WARNING
Even with
REQUIRE_USER_MATCH
set toFALSE
the NPS still queries the Entra ID for the user authentication methods. If the user is not found, the authentication will fail. Therefore, ensure that all users utilizing the NPS/VPN are synchronized with Entra ID.
For users who are not present in Entra ID you’ll see these errors:
EventID | Log | Details |
---|---|---|
6273 | Security | Reason Code: 21 Reason: An NPS extension dynamic link library (DLL) that is installed on the NPS server rejected the connection request. |
1 | Application and Services Logs\Microsoft\AzureMfa\AuthZ | NPS Extension for Azure MFA: CID: 430ef057-7941-44ff-a0b1-240e7d74cedc : Access Rejected for user |
The errors are shown below:
Resources
- https://learn.microsoft.com/en-us/entra/identity/authentication/howto-mfa-nps-extension
- https://learn.microsoft.com/en-us/entra/identity/authentication/howto-mfa-nps-extension-advanced
- https://learn.microsoft.com/en-us/entra/identity/authentication/howto-mfa-nps-extension-vpn
- https://wiki.freeradius.org/config/Radclient