These legacy instructions are outdated, preserved here for customers who are already using the pam_python method and need to refer to it.

Please see the Linux systems documentation page for the updated procedure.








Debian-like systems

Install packages and files

  • Install the pam_python library.  On Debian-like systems:
sudo apt install libpam-python
  • Copy the file to the directory /lib/security.

Configure PAM

The PAM configuration needs to change so that the authentication calls before the Active Directory authentication. 

If the PAM configuration is managed by auth-update-pam, you can accomplish this via:

  • Copy the file authlite to the directory /usr/share/pam-configs
  • Run the command:
sudo pam-auth-update
  • Now verify that the file /etc/pam.d/common-auth has the line:
auth  optional

above all other "auth" lines.

If the PAM configuration is managed manually: The goal is that whatever configuration file is being used for your authentication should have a line like:

auth  optional

appear above all other "auth" lines.

Now add:


at the end of the auth line following (which may be pam_unix or pam_lsass depending on the system used for domain joining) if it is not already there.

Next: see "Configure AuthLite" section below.

Redhat/CentOS-like systems

Install pam_python files

There is no pre-packaged pam_python module for CentOS, so it must be built from source

  • tar -xzf the .tar.gz file and go into the src subfolder
  • In pam_python.c, move the #include for Python.h above the #include for pam_modules.h

  • "make".  

    Then copy and to /usr/lib64/security.  If it is a 32-bit machine it would be /usr/lib/security.

Configure PAM

The pam configuration will vary depending on how you have joined to the domain.  In our test lab using SSSD, we modified /etc/pam.d/password-auth AND /etc/pam.d/system-auth directly, adding:

auth   optional /usr/lib64/security/ 

above the line for SSSD or Centrify.  Make sure you specify the correct full path to your script (lib or lib64 security).

For SSSD, add "use_first_pass" to the line, so it can see the password result from the pam_python module.

For Centrify, add "try_first_pass" to the line.

Configure SSSD

If using SSSD, go into the sssd.conf file and add the "ad_server" setting, to specify an exact order for your DCs to be used. This counteracts aggressive load balancing that can cause the OTP to go to one DC but the password to another. Example:

ad_server = the.fqdn.of.server1,fqdn.server2,_srv_

(put _srv_ at the end, like that)

Also set:

cache_credentials = False

After making any changes, bounce SSSD service and whatever logon system is affected by pam config updates (e.g. ssh)

Configure AuthLite

Add the linux computer account (or a security group containing the computer account) to the following AuthLite settings:

  • Forced 2-Factor Computers (because linux generally can't see group policy enforcement)
  • LDAP Permissions (because linux does an OTP lookup and then throws it away and sends the authentication request without the OTP)
  • Sticky 2-Factor Computers (because SSSD does several authentications in a row without the OTP)

These settings will take 20 minutes to apply (plus time for inter-site replication, if applicable)

Test authentication

YubiKey: After entering your password, tap the YubiKey button to enter the OTP.  Wait for the green light to come back on, to see that the OTP is finished.  Then hit enter.

OATH: After entering your password, enter a dash (-) and then the current OTP digits for this user.


Look at your system logs in /var/log. They will squawk if pam can't find the pam_python module, the script or other similar things.