Prompting For Multiple Authentication Types

Related ticket(s):

Problem statement

Currently FreeIPA only allows one authentication type at a given time for a user. Even if both authentication types ‘password’ and ‘otp’ were configured for the user only ‘otp’ was allowed in that case. Because of this SSSD only had to prompt for either ‘Password’ or ‘First factor’ and ‘Second factor’.

New version of FreeIPA will allow that the sue can authentication with different authentication types at the same time (https://pagure.io/freeipa/issue/433). SSSD now must prompt the user differently to make clear which authentication types are available for the user ideally without making the login process more complicated.

Use cases

(taken from http://www.freeipa.org/page/V4/Authentication_Indicators)

Strong Authentication on Selected System

User story

As an Administrator, I want to setup authentication to a critical system in my infrastructure (gateway VPN, accounting system) to only allow IdM users authenticated via strong authentication methods (2FA). I do not want to require strong authentication on other systems.

Description

A realm has two servers configured for ssh which use the following principals configured with authentication indicators:

host/lowsecurity.example.com []
host/highesecurity.example.com [otp radius]

When the administrator logs in using both his password and an OTP token, he can access both systems via ssh. However, when the administrator logs in using just a password, he can only access lowsecurity.example.com.

Overview of the solution

Depending on the available authentication types SSSD will show different login prompts:

Authentication types Login Prompt
password Password:
otp First factor: Second factor:
password + otp First factor or password: Second factor, press return for Password authentication:

If Smartcard authentication is enabled (pam_cert_auth = True) and a Smartcard is inserted in a reader with a certificate matching the user who wants to login the login prompt will ask for the Smartcard PIN for local authentication. (https://docs.pagure.org/SSSD.sssd/design_pages/smartcard_authentication_step1). Upcoming support for pkinit might lead to another extension of the prompting scheme.

Implementation details

First it has to be noted that this feature is related to Kerberos authentication because here the available authentication types are indicated by the server during the authentication request. Other authentication schemes like e.g. LDAP bind based authentication do support multiple different methods as well, e.g. you can bind to the FreeIPA LDAP server with password and 2FA authentication if the user is configured accordingly. But here the client either has to try which authentication might work or figure out possible authentication methods by other means which might be unreliable.

Kerberos indicates the available authentication methods via the available pre-authentication methods listed in the ‘Additional pre-authentication required’ response. The different pre-authentication methods are implemented as plugins and there are two ways for the plugins to interact with a user. The first one is a prompter callback which can be given as argument to e.g. krb5_get_init_creds_password(). The second, newer and more advanced method, are responders which can be set with krb5_get_init_creds_opt_set_responder() which is available since version 1.11 of MIT Kerberos.

For older versions of Kerberos where krb5_get_init_creds_opt_set_responder() is not available nothing changes because those versions do not support OTP either, so only password authentication will be available here.

For builds with a newer version of MIT Kerberos all authentication decision will be moved to the responder. This means that calls like krb5_get_init_creds_password() will not get the password as an argument anymore but the password is set inside of the responder if password based authentication is chosen.

The responder will check which authentication types are available by calling krb5_responder_list_questions(). If password authentication is available, indicated by the value of KRB5_RESPONDER_QUESTION_PASSWORD and the provided authentication token is of type password as well the password is set as answer to the password authentication and no further methods are considered.

If password authentication is not available or the provided authentication token is of type SSS_AUTHTOK_TYPE_2FA the existing OTP responder component is called.

During the SSSD pre-authentication request a new pam response is added which indicate that password authentication is available. Based on this and the OTP related response the pam_sss PAM modules can choose the right set of prompts.

Configuration changes

No configuration changes are needed on the client the available authentication types are determined based the the responses of the server.

How To Test

First create an IPA user and assign an OTP token to the user, see http://www.freeipa.org/page/V4/OTP#How_to_Test for details. Additionally two services with different authentication indicator requirements are useful to test the returned credentials but are not necessary to test the prompting.

$ ipa service-add ANY/ipa-client.example.com
$ ipa-getkeytab -p ANY/ipa-client.example.com -k /tmp/any.keytab

$ ipa service-add OTP/ipa-client.example.com --auth-ind=otp
$ ipa-getkeytab -p OTP/ipa-client.example.com -k /tmp/otp.keytab

(the keytab files are not needed for further testing).

Password only

To test plain password authentication call

$ ipa user-mod test_user --user-auth-type=password

and then as an un-privileged user

$ su - test_user
Password:

after login you can test by calling

$ kvno ANY/ipa-client.example.com@EXAMPLE.COM
ANY/ipa-client.example.com@EXAMPLE.COM: kvno = 1
$ kvno OTP/ipa-client.example.com@EXAMPLE.COM
kvno: KDC policy rejects request while getting credentials for OTP/ipa-client.example.com@EXAMPLE.COM

that only a ticket for the ANY service can be requested but not for the OTP service because only the password was used for authentication. Entering Password+TokenValue in a single string at the Password: prompt will cause an authentication failure.

OTP only

The second test is for OTP only authentication

$ ipa user-mod test_user --user-auth-type=otp

and then as an un-privileged user call

$ su - test_user
First Factor:
Second Factor:

after login you can test by calling

$ kvno ANY/ipa-client.example.com@EXAMPLE.COM
ANY/ipa-client.example.com@EXAMPLE.COM: kvno = 1
$ kvno OTP/ipa-client.example.com@EXAMPLE.COM
OTP/ipa-client.example.com@EXAMPLE.COM: kvno = 1

that tickets for both services can be request successfully because now 2-Factor authentication was used to log in. Entering Password+TokenValue in a single string at the First Factor: prompt will authenticate the user successfully as well but features like off-line authentication or unlocking of the user’s keyring might not be available.

Password and OTP

Finally both authentication methods are enabled on the server:

$ ipa user-mod test_user --user-auth-type=otp --user-auth-type=password

If now call su as an un-privileged user

$ su - test_user
First Factor or Password:
Second Factor, press return for Password authentication:

you can either just enter the password and press enter at the second prompt or enter the password and the OTP token value at the respective prompt. In the first case only a ticket for the ANY service can be requested:

$ kvno ANY/ipa-client.example.com@EXAMPLE.COM
ANY/ipa-client.example.com@EXAMPLE.COML: kvno = 1
$ kvno OTP/ipa-client.example.com@EXAMPLE.COM
kvno: KDC policy rejects request while getting credentials for OTP/ipa-client.example.com@EXAMPLE.COM

If both factor are given tickets for both services can be requested successfully:

$ kvno ANY/ipa-client.example.com@EXAMPLE.COM
ANY/ipa-client.example.com@EXAMPLE.COM: kvno = 1
$ kvno OTP/ipa-client.example.com@EXAMPLE.COM
OTP/ipa-client.example.com@EXAMPLE.COM: kvno = 1

Entering Password+TokenValue in a single string at the First Factor or Password: prompt will cause an authentication failure.

How To Debug

If password authentication is not working when both password and OTP authentication are enabled you might hit https://bugzilla.redhat.com//show_bug.cgi?id=1340304 and should update the Kerberos packages.

Inspecting log files

Setting debug_level = 9 in the [domain/…] section of sssd.conf will add libkrb5 trace messages to the krb5_child.log file which e.g. will show the pre-authentication methods offered by the KDC. Based on this SSSD will determine which authentication methods are available. In the Processing preauth types: line of the trace output 141 represents the OTP authentication while 2 (without FAST) or 138 (with FAST) stand for password authentication.

Manual testing with kinit

If only password authentication or password and OTP authentication are configured for a user kinit should ask for the password:

$ kinit test_user
Password for test_user@EXAMPLE.COM

OTP authentication is only available if FAST is enabled. The needed armor credential cache must be requested with kinit as well:

$ kinit -c ./armor.ccache -k

which will use the default keytab (/etc/krb5.keytab) which is accessible only by root to get a TGT. For easier testing you can create a special service and give suitable permissions to the service keytab. To use it with kinit use the -t option

$ kinit -c ./armor.ccache -k -t ./service.keytab

Now you can call

$ kinit -T ./armor.ccache test_user
Enter OTP Token Value:

If OTP is not enable for the user you should see the password prompt.

As usual, setting KRB5_TRACE=/dev/stdout before calling kinit or kvno will produce some extra output which might be useful.

Authors