ADFS OTP Provider

OTP authentication for Microsoft ADFS. It is a module for Microsoft ADFS 2019 or ADFS 2016 servers. It enables ADFS servers to provide multi-factor authentication (MFA) using a Time-Based One-Time Password (TOTP) Algorithm which is based on RFC6238. Using this MFA provider users are required to enter a one time passcode, which is generated on their phones via authenticator application like Microsoft Authenticator , Google Authenticator, Symantec VIP etc. to complete second factor authentication logon.


Unlicensed version

  • OTP passcodes for 24 user accounts.

  • OTP user accounts deactivation

  • OTP data storage in MS SQL service

  • Self-registration with QR code (using free Microsoft Authentication, Google Authentication, Symantec VIP etc. mobile apps)

  • Logs in Windows Applications Log

  • ADFS 2016 and ADFS 2019 support

  • Offline QR code generator (Integrated into adapter)

  • QR code customizations. (Advanced configuration)

  • OTP validity length can be customised

  • Support of ADFS CSS themes

Licensed version (additional features)

  • OTP passcodes for unlimited user accounts

  • OTP data storage in MS Active Directory attributes or MS SQL Service

  • OTP account lockout feature.

  • QR secrets encryption with AES 256-bit encryption.

  • Configuration of network locations (IPv4 and IPv6) from which user can scan QR code.

  • User interface customizations

  • Free version notes are removed

Deploy SecureMfaOtp adapter into AD FS farm

Preparation steps

Before you can start registering “SecureMfaOtpProvider” into your ADFS farm you must complete bellow steps. All commands must be executed in elevated PowerShell (PS) command prompt.

1) Deploy latest “SecureMfaOtpprovider” PowerShell module from Microsoft PSGallery using bellow PS command:

Install-Module -Name SecureMFA_OTP -Repository PSGallery -Scope AllUsers

NOTE: If your ADFS server doesn’t have access to the Internet you can pull PowerShell module from Windows client which has Internet access using bellow PS command:

Find-Module -Name "SecureMFA_OTP" -Repository "PSGallery" | Save-Module -Path "C:\"

Copy C:\SecureMFA_OTP folder from client’s computer into ADFS server “C:\Program Files\WindowsPowerShell\Modules\SecureMFA_OTP”

As alternative you can download “SecureMFA_OTP” nupkg file manually from website. Rename nupkg file’s extension into ZIP. Unzip content into a folder “SecureMFA_OTP” and place it into PS Modules default location on the server. That will work the same way as pulling package with native windows PS Tools.

2) Within “C:\Program Files\WindowsPowerShell\Modules\SecureMFA_OTP” directory you will find “sql_Create_Database_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”

3) Within “C:\Program Files\WindowsPowerShell\Modules\SecureMFA_OTP” directory update “SecureMfaOtpProvider.json” file.

If you are using a free version you only need to modify "sqlserver" server settings. If you will buy a license for unlimited users you will need to update "company" , "serialkey" and "subscriptionid" information to unlock licensed provider features.

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.

4) 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

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",

"subscriptionid": "1000000000000000000000001",

"sqlserver": "asqlaol1.adatum.labnet,1433",

"sqldbname": "SecureMfaOTP",

"sqlintegratedsecurity": "true",

"sqluseraccount": "",

"sqluserpassword": "",

"data_encryption": "false",

"data_encryption_passphrase": "d9GhT=7=Ox8-+LaZ",

"ui_customization": "false",

"ui_first_login_text": "",

"ui_login_text": “”,

"ui_allow_qr_display_from_networks": ";;",

"ui_login_failures": "0",

"ui_lockout_minutes" : "5",

"totp_customization": "true",

"totp_remove_user_prefix": "true",

"totp_offline_qr_enable": "true",

"totp_offline_qr_algorithm": "SHA1",

"totp_offline_qr_period": "30",

"totp_api_endpoint": "",

"totp_api_otpauth_advanced_params": "&algorithm=SHA1",

"totp_image_width_pixels": "150",

"totp_image_height_pixels": "150",

"auth_mode": "MSSQL",

"verboselog": "false"


Any configuration changes in json configuration file requires Install-SecureMfaOtpProvider to be run.

SecureMfaOtp adapter installation

Before a SecureMfaOtpprovider will be invoked by AD FS, it must be registered in the system. with PowerShell command which performs the necessary installation actions including installation in the GAC, and registration in AD FS farm.

Primary ADFS node

Bellow command will install OTP authentication provider on the MAIN ADFS node.


Other ADFS node(s)

Bellow command will install OTP authentication provider on OTHER ADFS node(s).

Install-SecureMfaOtpProvider -NotMainNode

NOTE: If you are using federation server farm that uses Windows Internal Database, you must start installation using the primary federation server of the farm as a MAIN node. Installation needs to be executed on ADFS farm server (not web application proxy servers).

Database access configuration

Provider supports all MS SQL Version and WID for backend configuration data. Use SecureMfaOtpProvider.json file to configure different access options. Note: asqlaol1.adatum.labnet value needs to be replaced with your SQL servers FQDN.

Access using:

Hostname and port: "sqlserver": "asqlaol1.adatum.labnet,1433"

Named SQL Instances (SQL-Cluster): "sqlserver": "asqlaol1.adatum.labnet\\Live01"

Local SQL Express Edition: "sqlserver": "localhost\\SQLEXPRESS"

Local WID DB using pipes: "sqlserver": "\\\\.\\pipe\\MICROSOFT##WID\\tsql\\query"

NOTE: WID DB option is only suitable for specific scenarios where you manage your infrastructure as a code. This is important because WID databases do not retain access to additional databases after servers’ restart and your code must handle these situations. This would be only for specific scenarios where MS SQL Express or AD attributes are not an option and you design a complicated flow for your OTP data across your environment.

If database access cannot be done with ADFS service account to SQL backend by using windows integrated authentication, you will need to chnage sqlintegratedsecurity value to false and update sqluseraccount and sqluserpassword with local SQL account details.

"sqlintegratedsecurity": "false",

"sqluseraccount": "sa",

"sqluserpassword": "Password",


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"

Disable User

This feature allows to disable SecureMFA OTP account and immedicably restrict MFA authentication without disabling user in Active Directory.

User will be getting following message If user’s SecureMFA OTP account has been disabled by support team.

How to disable SecureMFA OTP accounts please read “SecureMFA Support Tools” documentation.

Support tools are packaged into a separate PowerShell module which is used for OTP support and maintenance tasks.


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 (Lower range address / upper range address) and each location is separated by semicolon. CIDR format is not supported. Range values are inclusive.

To cover CIDR block range use following rules:

For IPv4 addressing – host range (For example translates into host range: /

For IPv6 addressing – network range (For example fe80::/64 translates into network range: fe80:0000:0000:0000:0000:0000:0000:0000 / fe80:0000:0000:0000:ffff:ffff:ffff:ffff or you can use a valid short IPv6 address text representation ( defined by rfc5952) : fe80::/fe80::ffff

Below is a sample of valid configuration

"ui_allow_qr_display_from_networks": “;;;ee80:e1::/ee80:e1::ffff”


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

With URI:

QR code customizations

It is possible to 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 native (offline) QR generator to external provider like Google API or any other vendor API endpoint. 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 OTP Authenticator clients defaults to SHA1 encryption and use 30 seconds period to display OTP code.

To enable customization set:

"totp_customization": "true"

Enable Offline QR Generator

To enable offline QR generator which comes as integrated feature with adapter you need to set:

"totp_offline_qr_enable": "true" (note it must be used together with above setting)

This is most secure option as user’s secret doesn’t travel over internet to service provider to request QR code image for user’s secret key.

Additional customization settings can be done if your QR code reader supports advanced QR customization.

To configure higher encryption of secret on QR client you can change “totp_offline_qr_algorithm” value to be SHA256 or SHA512.

"totp_offline_qr_algorithm": "SHA1" (default and has best support across major OTP client vendors)

Bellow setting must always be set to be 30 seconds unless you have specific requirements to configure your QR client with different time period.

"totp_offline_qr_period": "30"

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"

Enable OTP codes with Active Directory

This feature is only available for licensed OTP providers. It allows to store User OTP attributes in Active Directory domain. This removes dependency and cost of having MS SQL service configuration to store OTP database. To enable this feature, you have to update SecureMfaOtpProvider.json file to enable AD mode and update encryption passphrase with your custom string which will be used to encrypt secret data in AD attribute. AD mode doesn’t support unencrypted secrets.

"auth_mode": "AD"

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

You will have to execute following script “Create_SecureMFA_OTP_AD_attributes.ps1” which comes with OTP provider on Read-Write domain controller. You need to execute this script on Read-Write domain controller with AD account which is member of Schema Admins group. SecureMFA OTP provider when operates in AD mode it requires custom Active Directory (AD) attributes to be created to store OTP data for the user. This action cannot be undone and needs to be tested in your TEST domain first before moving into PRODUCTION. New AD Schema Attributes will be added into custom SecureMFA Auxiliary Class and that Class will be added into Existing User Class as AD Schema best practices suggest. OID numbers for custom attributes are from SecureMFA Private Enterprise range assigned by . Which do not overlap with other vendors OIDs numbers used to create custom AD attributes.

Note: THIS ONLY REQUIRES IF YOU PLAN TO RUN SecureMFA OTP Provider in AD MODE. By default, write access to a new Active Directory attributes is allowed only for domain administrators. If you run ADFS under dedicated service account please make sure it has WRITE access to “sMFA-* user attributes”, in order for the provider to be able to update Active Directory user info.

Bellow print screen shows how AD user’s custom attributes will look like.

When user's OTP attributes are stored in Active Directory domain it is very important that user has a valid UPN (UserLogonName) populated in AD and not left blank as highlighted in yellow. If user has no valid UPN vaue , SecureMFA OTP Provider will fail to validate a user. Windows application log will generate an error for such event.

Enable API endpoint for QR Generator

Endpoint for QR generator API is specified under "totp_api_endpoint" value. (NOTE, it is only accessed by client computers, most likely user’s browser will need to access this endpoint to retrieve QR image, and this configuration only works when "totp_offline_qr_enable" is set to "false". Otherwise offline QR generator configuration takes precedence). 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

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:


The below system events in Windows Event log may be used to verify and troubleshoot SecureMfa OTP Provider:

Log Name: AD FS/Admin

All provider related logs are stored in Windows Application Event logs and some data in SQL table or AD Attributes.

Windows Application Event:

Source: Secure MFA OTP

Event ID 5550: Successful Configuration Events

Event ID 5551: Failed Configuration Events

Event ID 5552: Successful Provider Events

Event ID 5553: Failed Provider Events

Event ID 5556: Successful OTP Events

Event ID 5557: Failed OTP Events



[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;

AD Attributes:

[sMFA-OTP-lastlogon] – Time stapm of last successful logon;

[sMFA-OTP-logoncount] – Total number of successful user logons;

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

[sMFA-OTP-failedlastlogon] - Time stamp of last failed logon;

[sMFA-OTP-failedcode] – Last failed user’s input;

[sMFA-OTP-logonip] – IP address of remote user;

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

Patching and Upgrades

Provider is highly integrated with MS Framework classes and uses Windows OS components to deliver functionality.

To keep up to date with latest security updates you must constantly update your Operating System and MS Framework components using Microsoft Security updates.

For any feature updates please upgrade a provider by pulling latest version from PowerShell Gallery by using bellow command:

Install-Module -Name SecureMFA_OTP -Repository PSGallery -Scope AllUsers -Froce

You’ll need to repeating all deployment steps as it was done for original installation. If it is highlited in deployment notes that attribute store needs to be extended for OTP data, you’ll need extra step to complete your upgrade.

· If you are using to store your user OTP data in MS SQL you may need to execute “sql_Upgrade_From_Previous_Version.txt” on your SQL database.

· If you are using to store your user OTP data in AD you may need to execute “Create_SecureMFA_OTP_AD_attributes.ps1” on your Domain controller. (this usually is highlighted in a new release documentation)

Files can be found in a directory with other installation files. This will add any extra missing columns/attributes in the Database or AD.

OTP Users Management

Support tools for OTP Users management are packaged into a separate PowerShell module which can be used for OTP accounts management tasks.

For more details please read “SecureMFA Support Tools” documentation.

Install ADFS Demo with OTP and Web Portal for Users OTP Enrollment

"SecureMFA_OTP" PS Module contains deployment script which allows to deploy working ADFS service on a single server from scratch.

It will deploy SecureMFA OTP and Web Portal with all configuration stored in MS SQL Express Edition. This deployment is suitable only for demo environments and can be used for internal users self-enrolment when OTP codes are used in conjunction with SecureMFA RDS OTP solution.

For demonstration purposes please deploy latest MS SQL Express Free Edition using default Instance Name and Instance ID: SQLEXPRESS on computer where you will be executing PS command “Install-ADFS_Demo_with_OTP”


  • Deployment must be done with service account which will be used for ADFS service. Account must be member of Local Computer and Domain Administrators groups for ADFS service to register successfully.

  • AD joined Windows 2019 or 2016 server.

  • Valid computer certificate for ADFS Service communications. It needs to have CN name different than computer's FQDN

  • System which executes a script must have Microsoft Framework 4.6.1 and above installed.


1) Deploy latest “SecureMFA_OTP” and "SqlServer" PowerShell Modules from Microsoft PSGallery using bellow PS commands:

Install-Module -Name SecureMFA_OTP -Repository PSGallery -Scope AllUsers

Install-Module -Name SqlServer -Repository PSGallery -Scope AllUsers -allowclobber -confirm:$false

NOTE: If your ADFS server doesn’t have access to the Internet you can pull PowerShell module from Windows client which has Internet access using bellow PS command:

Find-Module -Name "SecureMFA_OTP" -Repository "PSGallery" | Save-Module -Path "C:\"

Copy C:\SecureMFA_OTP folder from client’s computer into ADFS server “C:\Program Files\WindowsPowerShell\Modules\SecureMFA_OTP”

Find-Module -Name "SqlServer" -Repository "PSGallery" | Save-Module -Path "C:\"

Copy C:\SqlServer folder from client’s computer into ADFS server “C:\Program Files\WindowsPowerShell\Modules\SqlServer”

As alternative you can download “SecureMFA_OTP” nupkg file manually from website. Rename nupkg file’s extension into ZIP. Unzip content into a folder “SecureMFA_OTP” and place it into PS Modules default location on the server. That will work the same way as pulling package with native windows PS Tools.

2) Install Computer certificate on server which has CN name different to computer's hostname. this certificate will be used for ADFS service.

3) Start deployment by using installed certificate’s thumbprint value. NOTE: You must be logged into computer with service account which is dedicated for ADFS service and account must be member of Domain Administrators group. It must have local administrative access to the server for installation to be successful .

Install-ADFS_Demo_with_OTP -adfs_certificate_thumbprint "285394eae4e52bf64d3b6f6c304584f30c3f004f"

4) When deployment is complete you can use client’s computer browser and navigate to “SecureMFA OTP Web Portal” by using ADFS server’s FQDN in URL : HTTP://FQDN/

Note: It is HTTP and not HTTPS , it's because we are running ADFS service and “SecureMFA OTP Web Portal” on the same single host. For production environments you need to have multiple servers and redistribute services on different hosts)

5) By clicking LOGIN link users will be redirected to ADFS login page

6) After successful logging user will be promoted to enrol his account with OTP scanning

7) After scanning OTP code with mobile device and authenticating, user will see access token information page. If you want to use this portal with RDS OTP Provider when using OTP access on Microsoft RD Gateway Servers. You will have to switch from WID to SQL database instance, because access for “SecureMFA RDS OTP Provider” needs to be done using same database (See “Switch WID to SQL Database” section for more details). This way you can use “SecureMFA OTP Web Portal” to enrol users for RD Gateway authentications.


If you need to access MS SQL Express database you will need to download and install “MS SQL Management Studio” on ADFS server separately. And use instance name to access "SecureMfaOTP" Database.

If you need to access IIS graphical interface to access “SecureMFA OTP Web Portal” settings, please install Management tools for IIS server on ADFS server using PS command.

Add-WindowsFeature web-management-console

Deployment Video

Bellow video shows how quickly you can enable MFA authentication on ADFS Service

Switch Local SQL Database to SQL Cluster Database

Please follow bellow steps if you want to switch from using WID database for storing OTP secrets into MS SQL instance database.

  • Within “C:\Program Files\WindowsPowerShell\Modules\SecureMFA_OTP” directory open “sql_Create_Database_SecureMfaOTP.txt” . file and modify FILENAME location to reflect your SQL server storage configuration. Open the script in SQL manager connected to SQL Cluster and execute it. This will create a new SQL database for “SecureMfaOtpprovider”.

  • Ensure that ADFS service account has read write access to "SecureMfaOTP" Database.

  • Update OTP provider’s “SecureMfaOtpProvider.json” configuration file with SQL Server settings. More details can be found in “Database access configuration” section.

  • Run Install-SecureMfaOtpProvider PS command to activate latest configuration for ADFS service.