In this article, we will show how to implement two-factor authentication (2FA) for users on a Windows domain using the free open-source multiOTP package. MultiOTP is a set of PHP classes and tools that allows you to implement an on-premises strong authentication server for HOTP and TOTP (Time-based One Time Password). You can use it both in Windows and in any other operating system (via RADIUS) to enable 2FA with a one-time password.
Once multiOTP is deployed, Windows prompts a user to enter a one-time password (OTP) that they receive from their mobile device/smartphone (from Microsoft or Google Authenticator, or another OTP generator). You can enable two-factor authentication for users to log in to Windows workstations or to access RDS hosts on Windows Server over RDP.
Installing MultiOTP in Active Directory Domain
In this section, we’ll show how to install multiOTP on Windows Server 2019 and configure user synchronization from Active Directory.
Let’s start with the configuration of a multiOTP server that will get users from Active Directory, generate unique QR codes for users, and validate the second factor.
Create a security group in Active Directory and add users to it who will be required to pass the second-factor verification when logging into Windows. Create a group using PowerShell:
New-ADGroup 2FAVPNUsers -path 'OU=Groups,OU=Munich,dc=woshub,DC=com' -GroupScope Global -PassThru –Verbose
Add users to the group:
Add-AdGroupMember -Identity 2FAVPNUsers -Members j.smith, k.berg, m.bakarlin
Create a new user in AD multiOTP that will be used to access the AD catalog (with minimal privileges):
$passwd = ConvertTo-SecureString -String "Paa32ssw0rd!" -AsPlainText -Force
New-ADUser -Name "multiotp_srv" -SamAccountName "multiotp_srv" -UserPrincipalName "[email protected]" -Path "OU=ServiceAccounts,OU=Munich,DC=woshub,DC=com" –AccountPassword $passwd -Enabled $true
Download the multiOTP archive – https://download.multiotp.net/.
Open the multiotp_5.9.2.1.zip archive and extract the windows directory from it to a folder on your local drive (C:\MultiOTP
).
Open the command prompt and go to the directory containing multiotp.exe:
CD C:\MultiOTP\windows
Using the commands below, we will configure MultiOTP LDAP settings to get users from the Active Directory database.
multiotp -config default-request-prefix-pin=0
multiotp -config default-request-ldap-pwd=0
multiotp -config ldap-server-type=1
multiotp -config ldap-cn-identifier="sAMAccountName"
multiotp -config ldap-group-cn-identifier="sAMAccountName"
multiotp -config ldap-group-attribute="memberOf"
multiotp -config ldap-ssl=0
multiotp -config ldap-port=389
REM Domain controller IP address:
multiotp -config ldap-domain-controllers=mun-dc1.woshub.com,ldap://192.168.15.15:389
multiotp -config ldap-base-dn="DC=woshub,DC=com"
REM Account for multiOTP authentication in AD:
multiotp -config ldap-bind-dn="CN=multiotp_srv,OU=ServiceAccounts,OU=Munich,DC=woshub,DC=com"
multiotp -config ldap-server-password="Paa32ssw0rd!"
REM Group of users you want to enable OTP for:
multiotp -config ldap-in-group="2FAVPNUsers"
multiotp -config ldap-network-timeout=10
multiotp -config ldap-time-limit=30
multiotp -config ldap-activated=1
REM Key to access a MultiOTP server:
multiotp -config server-secret=secret2OTP
Earlier we created the 2FAVPNUsers group and added 3 users to it. Synchronize AD users with multiOTP.
multiotp -debug -display-log -ldap-users-sync
LOG 2022-09-17 14:36:44 info LDAP Info: 3 users created, based on 3 LDAP entries (processed in 00:00:00) LOG 2022-09-17 14:36:44 debug System Info: *File created: c:\MultiOTP\windows\.\users\j.smith.db
In this case, multiOTP has found 3 users and synchronized them.
multiotp -debug -display-log -ldap-users-sync
Run webservice_install.cmd as administrator. It will install multiOTP web management interface.
Sign-in MUltiOTP web interface (http://127.0.0.1:8112/
) using default credentials (user: admin
, password: 1234
). Then it is recommended to change it.
Configuring MultiOTP Two-Factor Authentication for Domain Users
In the List of users section, you will see a list of domain users synchronized earlier (AD/LDAP source).
Select a user and click Print. You will see a user QR code to add to the authentication app.
Install the Microsoft Authenticator (or Google Authenticator) from Google Play or App Store on the user’s smartphone. Open it and scan the user’s QR code.
Then a new user account appears in the Authenticator app, which generates a new six-digit password (the second factor) every 30 seconds.
In the command prompt, you can make sure that multiOTP allows authenticating this user with OTP:
multiotp.exe -display-log j.smith 130186
where 130186 is a one-time password you get from the app.
LOG 2022-09-17 15:13:11 notice (user j.smith) User OK: User j.smith successfully logged in with TOTP token Filter-Id += "2FAVPNUsers"
You can also make sure that OTP is working correctly through the web interface. Go to Check a user section, enter a user name and a one-time password.
How to install and Configure MultiOTP CredentialProvider on Windows?
The next step is to install multiOTP-CredentialProvider on Windows computers you want to implement two-factor authentication using multiOTP. You can install CredentialProvider on any Windows 7/8/8.1/10/11 or Windows Server 2012(R2)/2016/2019/2022 host.
In this example, we will enable 2FA for RDP users to log in to an RDSH server running Windows Server 2019.
Download and install multiOTP CredentialProvider from GitHub https://github.com/multiOTP/multiOTPCredentialProvider/releases. The last available version is 5.9.2.1.
Run the installation:
- Specify the IP address of the server multiOTP is installed on.Remember to open a firewall port on the multiOTP server and client. You can open a port in Windows Firewall on a server using PowerShell:
New-NetFirewallRule -DisplayName "AllowMultiOTP" -Direction Inbound -Protocol TCP –LocalPort 8112 -Action Allow
- Enter the secret key from the multiOTP configuration ( server-secret) in the field Secret shared with multiOTP server;
- Select Windows logon type to apply OTP authentication. In our example, we will use 2FA for RDP logins only (OTP authentication mandatory for remote desktop only).
MultiOTP CredentialProvider keeps its settings in the registry: HKEY_CLASSES_ROOT\CLSID\{FCEFDFAB-B0A1-4C4D-8B2B-4FF4E0A3D978}
. If you want, you can change CredentialProvider settings here without reinstalling agent.
Restart the Windows Server RDS host and try to connect to it via RDP. After you enter your user credentials, a new one-time password window appears. Here you must enter a one-time password from your Authenticator app on your smartphone.
You can enable logging on your multiOTP server, it is useful for debugging:
multiotp -config debug=1
multiotp -config display-log=1
Your script is running from C:\MultiOTP\windows\ 2022-09-17 15:21:07 debug CredentialProviderRequest Info: *Value for IsCredentialProviderRequest: 1 0 MUN-SRVOTP1 2022-09-17 15:21:07 debug Server-Client Info: *CheckUserToken server request. 0 MUN-SRVOTP1 2022-09-17 15:21:07 notice j.smith User OK: User j.smith successfully logged in (using Credential Provider) with TOTP token 0 MUN-SRVOTP1 2022-09-17 15:21:07 debug Server-Client Info: *Cache level is set to 1 0 MUN-SRVOTP1 2022-09-17 15:21:07 debug Server-Client Info: *Server secret used for command CheckUserToken with error code result 0: secret2OTP 0 MUN-SRVOTP1
Remember to make sure that your AD domain synchronizes time with a reliable time source and client devices have the correct time. These are critical to the operation of OTP.
So, the configuration of multiOTP two-factor authentication in Windows Server is over. There are also scenarios of using multiOTP with a RADIUS server to authenticate almost any type of client using OTP. You can use OTP for extra protection of the RDP server against brute force attacks together with Windows Firewall rules.
15 comments
Do this also work with yubikeys or is an authenticator app mandatory?
Check this
PHP class to authenticate YubiKeys locally (Yubico OTP algorithm), without any dependency (no PEAR, no PECL, no cURL)
https://github.com/multiOTP/yubikey-class-php
I installed the webserver exactly as you wrote on windows server 2022, and 2019 and 2016 too. When I installed the install_webservice.cmd the browser poped up 127.0.0.1:8112 with an error message “502 Bad Gateway nginx/1.25.3”. i tried multiple browsers but didnt work. I tried with domain joined and workgroup computer also. Please write some instruction how to configure on windows. I installed 5.9.7.1 version.
Leaving this here in case it’s puzzling anyone else, this is what worked for me:
1. Run webservice_uninstall.cmd
2. Download and install specifically the latest x86 version version of Microsoft Visual C++ Redistributable (https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-microsoft-visual-c-redistributable-version)
3. Run webservice_install.cmd
4. Attempt to access the webservice
5a. If successful, move on
5b. If unsuccessful, navigate to the webservice folder inside of MultiOTP\windows and manually start as administrator start-nginx-php.cmd
This should get it going.
I got locked out, the server rebooted and MultiOTP took over everything, i did not have any users yet configured :/
I did this about a thousand times during my initial setup. If you can access the machine via a remote powershell session or have the ability to enable remote powershell via GPO you can fix it pretty easily. If you can’t gain access via remote powershell and it’s just a test machine you’re probably better off wiping it. Here are my full notes on removing the credential provider:
If you can get a PSSession already, start by downloading the file multiOTPCredentialProvider-unregister.reg from here: https://github.com/multiOTP/multiOTPCredentialProvider/tree/ad97a4879e62df708a592d5381404e1307c45de6/installer
Copy the file anywhere onto the locked machine via Powershell, the syntax for copying from server A to server B is as follows:
$b = New-PSSession REMOTECOMPUTERNAME
Copy-Item -ToSession $b C:\Programs\temp\test.txt -Destination C:\Programs\temp\test.txt
Replacing the source and destination with your own
Then connect to the client computer, the syntax is
Enter-PSSession -Computername REMOTECOMPUTERNAME
Navigate your Powershell session to where you placed the file, then run
reg import multiotpcredentialprovider-unregister.reg
The success text is this case is red and should read
reg : The operation completed successfully.
+ CategoryInfo : NotSpecified: (The operation completed successfully.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Now you’ll need to actually uninstall the credential provider
Still inside of your PSSession run this to get a list of applications
Get-WmiObject -Class Win32_Product | Select-Object -Property Name
Create a variable and map it to the name of the application as printed(the way your application is named may differ)
$MyApp = Get-WmiObject -Class Win32_Product | Where-Object{$_.Name -eq “multiOTP Credential Provider 5.9.7.1 (64 bit)”}
Then run
$MyApp.Uninstall()
You can re-run Get-WmiObject -Class Win32_Product | Select-Object -Property Name to ensure that the application was uninstalled
You should now be free to start again on the client system
Keep in mind your environment may differ from my own, this is just what worked for me
Thanks for the great instruction. I have set up, everything works. I have one question, after entering user name and password on the test workstation, I receive OTP prompt for every user, not only for users in 2FAVPNUsers group. Is it possible to disable OTP prompt for some users and enable for others?
It isn’t documented here, but you also need a “without2fa” security group for a mixed authentication environment to work reliably.
There’s a line in the config file mentioned as such in the full documentation for multiOTP:
ldap-without2fa-in-group: Special LDAP/AD group(s) for without2fa users
I created a security group in my domain simply called “without2FA”, added my non-2FA users to it, and updated the line in the config file to read:
ldap_without2fa_in_group=without2FA
Then reran multiotp -ldap-users-sync and got I had what I wanted, the users and groups that were added to my 2FAVPNUsers group were prompted for OTP, the users in my without2FA group weren’t.
Thanks Erik! I will try your suggestion and return with the feedback.
Create a registry entry under
HKEY_CLASSES_ROOT\CLSID\{FCEFDFAB-B0A1-4C4D-8B2B-4FF4E0A3D978}
named excluded_account and specify an account that should be excluded from 2FA. The format is required to be domain\username or computername\username.Hi
i Installed everything like it is decribed here (thanks in advance for that great work) and until the credential provider everything works fine.
With the new version from the credentialprovider you get below the server-secret an information that you should add IP and Subnet to the MultiOTP Server.
Iam not able to add anything and unfortunately i always get the message that the OTP ist wrong.
Tried with connection with HTTP and HTTPS, IP-adress and FQDN.
There is also nowhere a button to check the connection to the server which is very unlucky.
and i don’t find or get any log-data about the failed connection.
Did somebody has the same problem?
The multiOTP server should be accessible from the RDS host running the multiOTP-CredentialProvider over TCP port 8112. Check that this port is open:
TNC multiotp_server_name -port 8112
Hi thanks for your reply
In that case, i just only tried to use it a local PC. Not on RDS. within the new version you can decide when the MFA should work.
There are 3 Options like local, remote and locked.
I always tried local but it didn`t work.
Do i use the commend above at the MultiOTP Server right?
The architecture of the MultuOTP solution consists of two parts.
The first is the MultiOTP server itself. and the second is multiOTP-CredentialProvider. You can install both parts on a single host or split them.
The “no remote server, local multiotp only” option in the CredProvider installer means that both parts are installed on a single host. Do not enter remote connection settings in this case.
goodevening but which is otp secret shared key that i must to configure in provider? the password for the account that make login, the password of websere or the password that i’ve assigned to multiotp_srv