Skip to content

Using Authy or Google Authenticator for 2FA with XRDP

matt335672 edited this page Aug 20, 2020 · 36 revisions

Introduction

This page details how to use the Authy mobile phone app to provide a second factor when logging in to a Linux-based XRDP system.

Although this guide uses Authy, it should be equally applicable to any other app which supports TOTP password generation (e.g. Google Authenticator).

This guide is applicable to all v0.9.x XRDP versions. At the time-of-writing the current version of XRDP is v0.9.13.1. These versions of XRDP are not natively 2FA-aware. However it is possible to use feature of the Linux 'PAM stack' to work around this. This is explained further below.

Audience

The reader should be aware of what two-factor authentication (2FA) is, and why it is becoming increasingly important.

An effort has been made to explain other concepts along the way. This may make the document somewhat wordy for more technically advanced readers, but the aim here is to reach as wide an audience as possible.

CentOS 8.2.2004 is used as an example, but the method should be readily adaptable to other distros.

The author has only tested with guide with local users. However, there is no reason why it should not work in enterprise environments, with domain users provided via SSSD or otherwise. In these environments be aware that NFS home directories introduce significant technical challenges. These are not further considered here.

This guide focuses exclusively on XRDP. However, supporting other login methods such as SSH using the same technique and the same secret key is relatively simple once you understand the concepts in this guide.

Theory of operation

Technical terms and details

OTP

An OTP or 'one-time password' is a password which is only valid for a single use.

TOTP

This is an algorithm which allows a time-based one-time password to be used for authentication.

'Time-based' means the OTP is only valid for a few tens of seconds.

In order for this code to be generated and accepted, the authenticator and the authenticatee must share two data items:-

  • A secret key
  • The current time

TOTP is described further in RFC6238 or on Wikipedia.

PAM

PAM is the software stack which sits under most Linux applications, and is responsible for providing authentication services. PAM is extensively described elsewhere, including Wikipedia.

If you are not familiar with it, a good place to start is A.P Lawrence's understanding PAM page.

google-authenticator-libpam

This software consists of the following items:-

  • A program google-authenticator which allows a user to set up a shared secret which is stored both in Authy, and within the user's home directory in ~/.google-authenticator.
  • A PAM module pam_google_authenticator.so which processes the OTP generated by Authy using the secret in ~/.google-authenticator.

More details on this software can be found in the module README.md, the latest version of which is here.

For CentOS 8 users, version 1.07 of this software is packaged in the EPEL google-authenticator RPM.

PAM module processing

forward_pass / use_first_pass options

pam_google_authenticator.so has an important feature which we make use of here; when the module is configured with the forward_pass option, it will consider the password string entered by the user to be the user's normal password with the OTP appended to it.

The OTP is removed from the password string and processed by pam_google_authenticator.so. The remainder of the string (i.e. the normal password) is 'stacked' for other PAM modules to perform password checking.

Importantly, other PAM modules which support the use_first_pass option will need to be configured with this so that they pick up the stacked password and do not attempt to prompt the user for the password. The following modules will need this option, if you are using them:-

  • pam_sss
  • pam_unix
  • pam_userdb

nullok option

Another useful module pam_google_authenticator.so option which we make user of here is nullok. This allows users who have not yet configured OTP to log in.

Data flow

This diagram shows the main dataflows involved in the authentication process. The user logging in is a local user with a password stored in /etc/shadow.

Process overview

  • Check the target systems are configured normally.
  • Edit /etc/pam.d/xrdp-sesman to implement support for the Google authenticator PAM module as follows:-
    • Add the pam_google_authenticator.so module to the auth section, configured with nullok and forward_pass.
    • Add the use_first_pass option to other PAM auth modules which process the user's password
  • Have each user log in and set up their TOTP secret key.
  • Test user logins using their standard password with Authy-generated codes appended.

CentOS 8 example

Example pre-requisites

The reader is assumed to have a fresh copy of CentOS 8 available with the following features:-

  • The GNOME desktop is installed
  • The epel-release RPM has been installed
  • The xrdp and xrdp-selinux RPMs are installed from EPEL.
  • The system is provisioned with time via chrony or NTP so that time-based authentication can be used.
  • Home directories are unencrypted and writeable.
  • authselect has been used already, if appropriate.
  • Users are using the GNOME keyring, and /etc/pam.d/xrdp-sesman is configured appropriately.

Normal CentOS 8 PAM stack for xrdp-sesman

The file /etc/pam.d/xrdp-sesman will look like this for a system which supports GNOME keyring:-

#%PAM-1.0
# Generic Fedora config
#auth       include      password-auth
#account    include      password-auth
#password   include      password-auth
#session    include      password-auth

# Gnome specific Fedora config (auth stanza with GA)
auth       include      gdm-password
account    include      gdm-password
password   include      gdm-password
session    include      gdm-password

As shipped the password-auth stanzas are enabled. to get GNOME keyring working, these need to be commented out and the gdm-password stanzas enabled.

gdm-password is a file which ships with the gdm RPM. Its function is to ensure the pam_gnome_keyring.so modules gets called as required, and that the password-auth file is also included appropriately.

password-auth is called by many other PAM files. It performs generic password-based authentication. CentOS 8 provides this file as a soft-link to another file generated by the authselect utility:-

+-------------+             +--------------+             +---------------+
| xrdp-sesman | -includes-> | gdm-password | -includes-> | password-auth |
+-------------+             +--------------+             +---------------+
                                                           ^      |
+--------------+                                           |    soft-
| +--------------+                                         |    links
+-|Other modules |----------------includes-----------------+      |
  +--------------+                                                |
                    +-------------------------------+             |
                    | /etc/authselect/password-auth |<------------+
                    +-------------------------------+

2FA CentOS 8 PAM stack for xrdp-sesman

As previously described, we need make the following changes to the auth module type:-

  • Include pam_google_authenticator.so
  • Add use_first_pass to modules which normally might input a password.

The first of these is straightforward. The second is however not so straightforward, as the affected modules are stored within the password-auth file which

#%PAM-1.0
# Generic Fedora config
#auth       include      password-auth
#account    include      password-auth
#password   include      password-auth
#session    include      password-auth

# Gnome specific Fedora config (auth stanza with GA)
auth       include      gdm-password
account    include      gdm-password
password   include      gdm-password
session    include      gdm-password

As shipped the password-auth stanzas are enabled. to get GNOME keyring working, these need to be commented out and the gdm-password stanzas enabled.

gdm-password is a file which ships with the gdm RPM. Its function is to ensure the pam_gnome_keyring.so modules gets called as required, and that the password-auth file is also included appropriately.

password-auth is called by many other PAM files. It performs generic password-based authentication. CentOS 8 provides this file as a soft-link to another file generated by the authselect utility:-

+-------------+             +--------------+             +---------------+
| xrdp-sesman | -includes-> | gdm-password | -includes-> | password-auth |
+-------------+             +--------------+             +---------------+
                                                                  |
           +-------------------------------+                      |
           | /etc/authselect/password-auth |<-----soft-links------+
           +-------------------------------+