Setup oath ssh login on Fedora

There are occasions where I’d like to be able to ssh to a system without using the password or having to setup a ssh key. Another alternative for authentication is the pam_oath module which allows you to use OATH applications like FreeOTP or Google Authenticator for 2-factor logins.

Start by installing the required packages. This is specific to Fedora, other distributions will be similar but slightly different in fun and challenging ways.

yum install pam_oath oathtool gen-oath-safe

Setup the sshd pam configuration to use pam_oath by adding this to the first line of /etc/pam.d/sshd

auth sufficient pam_oath.so usersfile=/etc/liboath/users.oath window=10 digits=6

Make sure sshd has challenge/response enabled by editing /etc/ssh/sshd_config and making sure it has:

ChallengeResponseAuthentication yes

Restart sshd to make this take effect:

systemctl restart sshd

Run the gen-oath-safe script to generate a key and a QR code for your user account.

gen-oath-safe username@system hotp

Note that this will generate a counter based key. Use totp to generate a time based key. Add the key to Google Authenticator or FreeOTP using the QR code or the key that is displayed. You can ignore the output that mentions yubikey. Note that the username@system will be what is displayed in the application, so make it unique enough that it doesn’t collide with other keys.

oath qr code

Setup the user authentication by editing /etc/liboath/users.oath and adding a line:

HOTP username anicelongpin f3870328d2f9fdf2881e0f4c32a3c775240b4a9c

Where the hex string is the key generated by gen-oath-safe. Change HOTP to +HOTP/T30+ if you used totp with gen-oath-safe.

Setup the permissions so that only root can read it and so that SELinux works when sshd tries to access it.

chmod 0600 /etc/liboath/users.oath
semanage fcontext -a -t systemd_passwd_var_run_t '/etc/liboath(/.*)?'
restorecon -rv /etc/liboath/

This last part took me a bit to figure out, DDG and Google weren’t much help and finally I stumbled on a comment here that suggested how to set the type correctly. If you are running with SELinux disabled (why!?) then you can just chmod the file.

You should now be able to ssh to the system, and if there isn’t an authorized_key setup it will prompt 3 times for the OATH password, and then fall back to the user’s login password. Entering the PIN (anicelongpin in the example) followed by the 6 digit code from the authentication application should result in a successful login. If it fails, check the output of journalctl -f while trying to login.