Is there a way to enforce two-factor authentication (2FA) for all users on the SSH server on the Unix PAM Subsystem?

  • 2
    The SSH private key file doesn't qualify as "something they have"?
    – Sotto Voce
    Feb 2 at 16:32
  • 4
    There are many articles online that address exactly this question. Just cutting and pasting the title of this question into a search engine yields several relevant results.
    – larsks
    Feb 2 at 23:08
  • 2
    UNIX or Linux? The PAM subsystem allows for 2FA so your UNIX platform would need to support that. Does it? Feb 5 at 17:50
  • 2
    This is like pulling teeth. What UNIX system? What brand/manufacturer? What version? (It's moot now as I've written a Linux-specific PAM-generic answer, but next time please volunteer information.) Feb 5 at 20:45
  • 2
    @ChrisDavies I know, and I have upvoted it. However, at the time I wrote the comment, the question looked very different.
    – AdminBee
    Feb 6 at 10:54

1 Answer 1


I don't have access to the unnamed UNIX system such as yours, so you are going to have to adapt the solution I'm describing here for your own situation.  (Feel free to edit this answer to add your specifics.)

The PAM subsystem allows for the inclusion of additional modules in the authentication process.  One of these provides for Google Authenticator (and any compatible offering, such as the one from Microsoft).

BEFORE YOU START, make sure you have a root session established, and do not close it until you have verified with yet another connection that you can still login (and use sudo or su).

Here is the installation and configuration process for Debian 12 ("bookworm"). You will need to be root throughout, so start with sudo -s to get a root shell:

sudo -s

apt update
apt install libpam-google-authenticator

cp -p /etc/pam.d/common-auth{,.$(date +'%Y-%m-%d')}
echo 'auth required pam_google_authenticator.so nullok echo_verification_code' >>/etc/pam.d/common-auth

Now edit /etc/ssh/sshd_config (not ssh_config) and either add or edit these lines.  If you're adding them, put them immediately underneath UsePAM yes.

cp -p /etc/ssh/sshd_config{,.$(date +'%Y-%m-%d')}
vi /etc/ssh/sshd_config    # or nano, or any preferred editor

ChallengeResponseAuthentication yes
KbdInteractiveAuthentication yes

And restart sshd

systemctl restart sshd

Now log in as a normal user and set up the Authenticator.


   Do you want authentication tokens to be time-based (y/n) y
   Warning: pasting the following URL into your browser exposes the OTP secret to Google:

You will have a QR code displayed - either in your text terminal or when you click through the generated web page link. Snap that in the Authenticator app as usual.

   Your new secret key is: 4JD3xxxxxxxxxxxxxxxxxxH7EE
   Enter code from app (-1 to skip): xxxxxx
   Code confirmed
   Your emergency scratch codes are:

   Do you want me to update your "/home/{user}/.google_authenticator" file? (y/n) y
   Do you want to disallow multiple uses of the same authentication token? (y/n) y
   By default […] This will permit for a time skew of up to 4 minutes
   between client and server. Do you want to do so? (y/n) n
   Do you want to enable rate-limiting? (y/n) y

Now test. If it works, that's great. If not, then revert /etc/pam.d/common-auth and /etc/ssh/sshd_config and try again.

Be aware that because I have included the option nullok on the PAM configuration entry, users can choose to avoid setting up Authentication. If you remove that it becomes a required value. Take great care removing this option as it will enforce 2FA for all user accounts - including root. You can read up on the other options in the documentation (see man pam_google_authenticator and man google-authenticator).

  • Great answer! Wish this had been around when I set up GA on my cloud server so I didn't have to fumble through it. Feb 5 at 22:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .