MFA One Time Pass-code Provider v1.0.1.1


Unlicensed adapter

  • OTP passcodes can be used with 25 users for free.
  • Support of ADFS CSS themes
  • Enable self-registration with QR code (using free Microsoft Authentication, Google Authentication, Symantec VIP etc. mobile apps)
  • Logs are stored in Windows application log
  • Runs on ADFS 2016 and ADFS 2019 servers

Licensed adapter

  • OTP passcodes for unlimited user accounts of licensed organization.
  • QR code encryption with AES 256-bit encryption in SQL database.
  • Configuration of network locations from which user can scan QR code.
  • Text customization for adapter interface.
  • OTP account lockout feature.
  • QR code customizations. (Advanced configuration)
  • Free version notes are removed.

Release information


  • Release date 02/05/2019
  • Added QR code customizations feature for OTP code.
  • Allows configuration of network locations from which user can scan QR code to set OTP configuration on mobile device.

NOTE: Product encryption is not compatible with version If you are using encryption with previous version, after upgrade you’ll need to delete user’s encrypted secret and re-enrol users again. If you are upgrading from previous SecureMfaOtp please execute “sql_upgrade_from_previous_version.txt” query to add extra columns into SQL table.


Deploy SecureMfaOtp adapter into AD FS farm

Preparation steps

Before you can start registering “SecureMfaOtpProvider” into your ADFS farm you must complete bellow steps

1) Download latest “SecureMfaOtpprovider” package from .

2) Content will be downloaded as a zip file. Extract it on the primary ADFS server into “C:\SecureMfaOtpProvider” location.

3) Within the directory you will find “CreateDatabase_SecureMfaOTP.txt”

Modify FILENAME location to reflect your sql server storage configuration. Open the script in SQL manager and execute it. This will create a new SQL database for “SecureMfaOtpprovider”

4) Within the directory update “SecureMfaOtpProvider.json”

If you are using a free license you only need to modify "sqlserver" server settings . If you will buy a license for unlimited users you will need to update "company" and "serialkey" information to unlock the app.

If you are not running your adfs servers using service account and you cannot use SQL integrated security to access database, you need to change:

"sqlintegratedsecurity": "false“ and update "sqluseraccount" and "sqluserpassword" with relevant information.

5) If you need to generate verbose logs in windows events for troubleshooting reasons change verboselog value from “false” to “true”. Please note that verbose logging can affect your servers’ performance, use it only for troubleshooting reasons. Don’t enable “verboselog” in production environments as it may reveal configuration secrets

6) Using SQL manager provision dbo access to “SecureMfaOTP” database for ADFS service account or SQL user.

Below is a sample of a SecureMfaOtpProvider.json file

"company": "MyCompany",
"serialkey": "m00000000",
"sqlserver": "asqlaol1.adatum.labnet,1433",
"sqldbname": "SecureMfaOTP",
"sqlintegratedsecurity": "true",
"sqluseraccount": "",
"sqluserpassword": "",
"verboselog": "false",
"data_encryption": "false",
"encryption_passphrase": "d9GhT=7=Ox8-+LaZ",
"login_failures": "0",
"lockout_minutes" : "5",
"ui_customization": "false",
"ui_first_login_text": "",
"ui_login_text": “”,
"totp_customization": "false",
"totp_remove_user_prefix": "false",
"totp_api_endpoint": "",
"totp_api_otpauth_advanced_params": "&algorithm=SHA1",
"totp_image_width_pixels": "150",
"totp_image_height_pixels": "150"

SecureMfaOtp adapter installation

Before a SecureMfaOtpprovider will be invoked by AD FS, it must be registered in the system. Bellow powersehll script performs the necessary installation actions including installation in the GAC, and registration in AD FS farm.

Script to install SecureMfaOtpProvider on primary ADFS node

#Open elevated PowerShell command window on your federation server and execute the following commands
#Note that if you are using federation server farm that uses Windows Internal Database, you must execute these commands on the primary federation server of the farm
#Bellow commands needs to be executed on one server in ADFS farm

#Check if windows events source for application log exist, if not create one.
if ([System.Diagnostics.EventLog]::SourceExists("Secure MFA OTP") -eq $False) {New-EventLog -LogName "Application" -Source "Secure MFA OTP"}

#Remove additional authentication providers from ADFS global policy and unregister SecureMfaOtpProvider
Set-AdfsGlobalAuthenticationPolicy -AdditionalAuthenticationProvider ""
unregister-AdfsAuthenticationProvider -Name “SecureMfaOtpProvider” -Confirm:$false

#Restart ADFS service
net stop adfssrv
net start adfssrv

#Load GAC Assembly
Set-location "c:\SecureMfaOtpProvider"           
[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") 
$publish = New-Object System.EnterpriseServices.Internal.Publish  

#Remove SecureMfaOtpProvider DLL from GAC assembly

#Add SecureMfaOtpProvider DLL to GAC assembly         

#Register SecureMfaOtpProvider addapter
$typeName = “SecureMfaOtpProvider.AuthenticationAdapter, SecureMfaOtpProvider, Version=, Culture=neutral, PublicKeyToken=f818a38c51378814, processorArchitecture=MSIL”
Register-AdfsAuthenticationProvider -TypeName $typeName -Name “SecureMfaOtpProvider” -ConfigurationFilePath 'C:\SecureMfaOtpProvider\SecureMfaOtpProvider.json'

#ADFS 2019 requires update to http security headers to allow display of images for QR code to be display from external source. 
#You can update allows source with exact URL instated of any location (*).
if (Get-Command "Get-AdfsFarmInformation" -errorAction SilentlyContinue) 
    if ((Get-AdfsFarmInformation).CurrentFarmBehavior -ge 4) 
        Set-AdfsResponseHeaders -SetHeaderName "Content-Security-Policy" -SetHeaderValue "default-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src * data:;" ;
        (get-AdfsResponseHeaders).ResponseHeaders | fl ;

#Restart ADFS service
net stop adfssrv
net start adfssrv

#Add SecureMfaOtpProvider as additional authentication provider in ADFS
Set-AdfsGlobalAuthenticationPolicy -AdditionalAuthenticationProvider "SecureMfaOtpProvider"       

If you have more servers in ADFS farm execute following script on remaining nodes

Script to install SecureMfaOtpProvider on other ADFS nodes

#Open elevated PowerShell command window on your federation server and execute the following commands
#Note that you don't need to register DLL on ADFS proxy servers

#Check if windows events source for application log exist, if not create one.
if ([System.Diagnostics.EventLog]::SourceExists("Secure MFA OTP") -eq $False) {New-EventLog -LogName "Application" -Source "Secure MFA OTP"}

#Load GAC Assembly
Set-location "c:\SecureMfaOtpProvider"            
[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") 
$publish = New-Object System.EnterpriseServices.Internal.Publish            

#Remove SecureMfaOtpProvider DLL from GAC assembly

#Add SecureMfaOtpProvider DLL to GAC assembly         

#Restart ADFS service
net stop adfssrv
net start adfssrv

#List all authentication providers
Get-AdfsAuthenticationProvider | select name


To verify if “SecureMfaOtpProvider” has been installed successfully.

1) Open the AD FS Management Snapin (from Server Manager Tools menu)

2) Click Authentication Policies at left

3) In the center pane, under Multi-Factor Authentication, click the blue Edit link to the right of Global Settings.

4) Under Select additional authentication methods at the bottom of the page, check if “Time Based OTP Authentication Provider” is selected.


When you will login into your ADFS application which requires multifactor authentication first time user will see QR coder which can be scanned with any authenticator which is based on RFC6238 ( a Time-Based One-Time Password (TOTP) Algorithm). This algorithm is used in Google's Authenticator, Microsoft Authenticator, Symantec VIP and potentially in many other time-based authenticators.

Below is print screen of SecureMFA OTP provider.

After user’s successful logon using OTP code, QR code will never be displayed unless user’s account is deleted from “Secrets” table in SQL or “logon” value is updated to 0

User Lockouts

This feature only works for licensed adapters. If you set “login_failures” more than a zero in SecureMFA database you will see failed user authentication attempts. When user reaches “failedlogoncount” number of attempts set in “login_failures” value user’s account will be locked out for a period of time set in "lockout_minutes" . If you want to disable this feature you must set “login_failures” to zero. All values are configured in SecureMfaOtpProvider.json file.

SecureMfaOtpProvider.json config settings to enable 5 min lockouts for 15 failed OTP passcode attemps :

"login_failures": "15"
"lockout_minutes" : "5" 


Encryption only works for licensed adapters. AES 256-bit encryption is created with AesManaged class in the System.Security.Cryptography module: This class uses Windows CryptoAPI (CAPI) which uses FIPS-compliant .NET Assemblies. The cipher mode is Cipher Block Chaining (CBC). The passphrase can be configured in configuration file and it is recommended to be between 16-18 random characters. It is salted with 16 bytes string, zero padding and 4 key iterations. Full documentation on “AesManaged .NET class” can be found in Microsoft documentation for “System.Security.Cryptography.AesManaged“ constructors)

SecureMfaOtpProvider.json config settings to enable encryption:

"data_encryption": "true"
"encryption_passphrase": "d9GhT=7=Ox8-+LaZ"

When it is enabled your secret code is encrypted in Database and it looks like bellow.

Theme customizations

Licensed clients can customize adapter text which is presented to the users during logon. You can use some simple html code like links to provide users with self-service portal links etc. Text customizations are configured in “SecureMfaOtpProvider.json” file.

NOTE: "ui_customization" must be set to "true" for bellow changes to take effect.

"ui_first_login_text": "Please configure your Authenticator Application (Microsoft Authenticator, Google Authenticator, Symantec VIP etc.) using the QR code below."
"ui_login_text": "Enter the passcode generated by your authenticator application."

Configuration of network locations for QR code

Licensed clients can customize from which network locations users can scan their QR code for mobile device configuration.

Allowed network locations are configured in “SecureMfaOtpProvider.json” file.

NOTE: "ui_customization" must be set to "true" for bellow changes to take effect. List of locations must be specified as indicated in bellow format (SubnetID/MASK) and each location is separated by semicolon.

"ui_allow_qr_display_from_networks": “;;”


All successful second factor authentication sessions will issue a new Actual Authentication method value:

With URI:

QR code customizations

Licensed clients can customize QR code generated text and set advanced features for Authenticator software. QR image is presented to the user during first logon and allows to enrol user’s Authenticator device to generate OTP codes for the user. With customization settings enabled you can change QR code generator endpoint from Google API (which is default QR code generator for SecureMFA OTP adapter) to any other vendor or internal QR service. Any advance settings specified in QR customizations must be supported by OTP Authenticator software. Some OTP Authenticator software do not support QR codes with advance settings, some of them will ignore settings like SHA256 passphrase encryption on the client etc. Most popular Authenticator software defaults to SHA1 encryption.

To enable customization set:

"totp_customization": "true"

Endpoint for QR generator API is specified under "totp_api_endpoint" value. (NOTE, it is only used by client computer to access, most likely user’s browser will need to access this endpoint to retrieve QR image). It must be specified with all mandatory parameter values in URL which are required by a vendor. Only vendors who specifies TOTP settings under “otpauth://totp/” configuration will work. It must support following format: otpauth://[TYPE]/[KEY NAME]?secret=[KEY SECRET, BASE 32]&issuer=[ISSUER] . All those settings will be generated by SecureMFA OTP adapter and amended into API endpoint URL. Issuer and Label information will come from licensed company name. Not licensed adapters will show as issuer information.

"totp_api_endpoint": ""

Any advance settings which are supported by QR generator and client authenticator software must be specified under bellow setting. Set all required parameters separated by & symbol.

"totp_api_otpauth_advanced_params": "&algorithm=SHA1"

More details on advanced QR configuration can be found HERE

Bellow settings specifies HTML image size which will be displaying QR code, it must not be smaller than a size setting used in QR endpoint URL. It is recommended to match values.

"totp_image_width_pixels": "150",
"totp_image_height_pixels": "150"

If you need to hide user’s account prefix information as additional security feature on client’s device. Set “totp_remove_user_prefix” in json config file to be “true”

Bellow pictures shows how it looks with enabled and disabled user’s prefix on Authenticator’s screen.

"totp_remove_user_prefix": "true"

"totp_remove_user_prefix": "false"

Below is a sample of json configuration file which will work with API. It is another free QR image generator service available on the internet.

"totp_customization": "true",
"totp_remove_user_prefix": "true",
"totp_api_endpoint": "”
"totp_api_otpauth_advanced_params": "&algorithm=SHA1",
"totp_image_width_pixels": "150",
"totp_image_height_pixels": "150" 

Final URL for API endpoint to the user is unique. Below is a sample how properly formatted URL for QR image will look like:


All provider related logs are stored in Windows Application Event logs and som in SQL table.

Windows Application Event:

Source: Secure MFA OTP

Event ID 5550: Configuration Logs

Event ID 5552: Successful Events

Event ID 5553: Failed Events

SQL columns:

[lastlogon] – Time stapm of last successful logon;

[logoncount] – Total number of successful user logons;

[failedlogoncount] – Number of failed logons in a row;

[failedlastlogon] - Time stamp of last failed logon;

[failedcode] – Last failed user’s input;

[logonip] – IP address of remote user;

[useragent] – Details of user’s agent details from last logon;