The Shibboleth V2 IdP and SP software have reached End of Life and are no longer supported. This documentation is available for historical purposes only. See the IDP v4 and SP v3 wiki spaces for current documentation on the supported versions.

Multi Factor Login Handler

  • The multi-factor-login-handler is similar to the UsernamePassword login handler, but can be configured to require more than one authentication factor.
  • The first factor is likely your existing password solution (like Kerberos or LDAP) and the second factor a hardware token, such as an OATH-HOTP token.

Installation and configuration

Download and install the login handler

# From source :
git clone git://github.com/Yubico/yubico-shibboleth-idp-multifactor-login-handler.git multifactor-login-handler
cd multifactor-login-handler
mvn package
cp target/multifactor-login-handler-*.jar $IDP_INSTALL_DIR/lib

Configuration

Login pages

Two factor login

  • You can use multifactor-login-handler/examples/login.jsp as an example.
  • Place it in $IDP_INSTALL_DIR/src/main/webapp/
    • The example provided can be used with both this and the UsernamePassword login handler without changes, so replacing the default one seems easiest. If you have customized the IdP login page you'd need to redo the customization again to this version, or simply add the changes between this example and the upstream login.jsp to your customized version.

Web application

Enable the the Multi Factor login servlet in $IDP_INSTALL_DIR/src/main/webapp/WEB-INF/web.xml or in your copy outside the WAR file in $IDP_HOME/conf/web.xml:

<webapp>
    <!-- ... -->
    <!-- Servlet for doing multi factor authentication -->
    <servlet>
        <servlet-name>MultiFactorAuthHandler</servlet-name>
        <servlet-class>com.yubico.shibboleth.idp.multifactor.MultiFactorAuthLoginServlet</servlet-class>
        <load-on-startup>4</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>MultiFactorAuthHandler</servlet-name>
        <url-pattern>/Authn/MultiFactor</url-pattern>
    </servlet-mapping>

    <!-- ... -->
</webapp>

Note that using the MultiFactor login handler as the only login handler practically restricts the entire IdP to uses with Tokens. This is because once this login handler runs (whether requested by a relying party or by IdP configuration) it will unconditionally assert a SAML Authentication Context Class of "urn:oasis:names:tc:SAML:2.0:ac:classes:Token", even if the underlying JAAS module stack is configured to make use of a Token fully optional (i.e., only username and password have been provided).

 

Using MultiFactor and UsernamePassword together

So it seems best to use the UsernamePassword login handler as well, for any uses that don't require a token. This limits the use of the MultiFactor login handler to those cases where provding an OTP token is in fact strictly required and requested by a Relying Party. Note that peter had to add a defaultAuthenticationMethod="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" on the <rp:DefaultRelyingParty> element in $IDP_HOME/conf/relying-party.xml as the MultiFactor login handler took precedence. If you have custom <rp:RelyingParty> elements defined that may also be necessary for those.

For that change the jaasConfigName parameter for this login handler so that both JAAS configurations do not conflict even when using the same JAAS config file. This is again accomplished in $IDP_INSTALL_DIR/src/main/webapp/WEB-INF/web.xml or your copy in $IDP_HOME/conf/web.xml: (see IdPAuthUserPass#IdPAuthUserPass-AdvancedConfigurationOptions):

<webapp>
    <!-- ... -->
    <!-- Servlet for doing multi factor authentication -->
    <servlet>
        <servlet-name>MultiFactorAuthHandler</servlet-name>
        <servlet-class>com.yubico.shibboleth.idp.multifactor.MultiFactorAuthLoginServlet</servlet-class>
        <init-param>
            <param-name>jaasConfigName</param-name>
            <param-value>ShibMultiFactorAuth</param-value>
        </init-param>
        <load-on-startup>4</load-on-startup>
    </servlet>

    <!-- ... -->
</webapp>

Do not forget to propagate this change in your JAAS configuration file referenced by jaasConfigurationLocation below, as per the examples. You may re-use the existing login.config and simply add another ShibMultiFactorAuth stanza to it (after the ShibUserPassAuth one), or reference a different file.

Handler configuration

In $IDP_HOME/conf/handler.xml, add the xsd schema in the <ProfileHandlerGroup> :

<ph:ProfileHandlerGroup xmlns:ph="urn:mace:shibboleth:2.0:idp:profile-handler" xmlns:multifactor="http://www.yubico.com/2011/shibboleth/idp"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="urn:mace:shibboleth:2.0:idp:profile-handler classpath:/schema/shibboleth-2.0-idp-profile-handler.xsd
                        http://www.yubico.com/2011/shibboleth/idp classpath:/schema/shibboleth-2.0-idp-multifactor-login-handler.xsd">

Also in $IDP_HOME/conf/handler.xml, add the new Login Handler :

    <!-- ... -->
    <!-- Login Handlers -->

    <!-- Multi Factor Login Handler -->
    <!-- configuration attributes: -->
    <!-- jaasConfigurationLocation (required): path to a JAAS login.conf -->
    <ph:LoginHandler xsi:type="multifactor:MultiFactorAuth"
                     jaasConfigurationLocation="file:///path/to/shibboleth/idp/conf/mf-login.config">
        <ph:AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:Token</ph:AuthenticationMethod>
    </ph:LoginHandler>
    <!-- ... -->

As mentioned above you can re-use the same jaasConfigurationLocation as for the UsernamePassword login handler ( $IDP_HOME/conf/login.config) by including a named section for each use in that file. See the YubiKey example below.

JAAS configuration

OATH-HOTP example

This example adds a second authentication factor that lets you use any OATH-HOTP token by validating that the token provided by the user can be used to access a OATH-HOTP basic auth protected web page.

  • Get and install the HttpOathOtpLoginModule JAAS module.
# From source :
git clone -b feature/shibboleth_multifactor_auth git://github.com/Yubico/yubico-java-client.git yubico-java-client
cd yubico-java-client
mvn package
cp target/yubico-validation-client-*.jar $IDP_INSTALL_DIR/lib

# Pre-compiled :
cd $IDP_INSTALL_DIR/lib
wget https://github.com/downloads/Yubico/yubico-java-client/yubico-validation-client-2.0-pre1-shib.jar
# (signature at https://github.com/downloads/Yubico/yubico-java-client/yubico-validation-client-2.0-pre1-shib.jar.asc)
	<Directory "/var/www/oath-protected">
	    AuthType basic
	    AuthName "My Protected Area"
	    AuthBasicProvider OTP
	    OTPAuthUsersFile /path/to/oath-users.txt
	    Require valid-user
	</Directory>
  • Create /var/www/oath-protected/index.html with some known content, like "Authenticated OK.".
  • Set up a two-factor JAAS configuration mf-login.conf (making sure the name matches the cnofigured jaasConfigName in your web.xml):
ShibUserPassAuth {

   edu.vt.middleware.ldap.jaas.LdapLoginModule required
      ...;

   com.yubico.jaas.HttpOathOtpLoginModule sufficient
      protectedUrl = "http://auth.example.com/oath-protected/"
      expectedOutput = "Authenticated OK.";
};

See yubico-java-client/src/main/java/com/yubico/jaas/README for further details about HttpOathOtpLoginModule configuration.

YubiKey example

This example adds a second authentication factor that lets you use a YubiKey OTP token by validating that the token provided by the user (1) may be used by the authenticated subject and (2) can be validated by a YubiKey OTP validation service (one you run yourself or the "cloud" service Yubico provides.)

  • Get and install the YubikeyLoginModule JAAS module.
# From source :
git clone git://github.com/Yubico/yubico-java-client.git
cd yubico-java-client
mvn package
cp jaas/target/yubico-jaas-module-*-jar-with-dependencies.jar $IDP_INSTALL_DIR/lib
  • Set up a two-factor JAAS configuration in the referenced jaasConfigurationLocation file, e.g. when re-using login.config for both login handlers:
ShibUserPassAuth {
// unmodified from your ordinary use with the UsernamePassword login handler, e.g.
/*
   edu.vt.middleware.ldap.jaas.LdapLoginModule required
      ldapUrl="ldap://ldap.example.org"
      baseDn="ou=people,dc=example,dc=org"
      ssl="true"
      userFilter="uid={0}";
*/
};
 
ShibMultiFactorAuth {
// copy your first factor from the ShibUserPassAuth stanza above, e.g.
/*
   edu.vt.middleware.ldap.jaas.LdapLoginModule required
      ldapUrl="ldap://ldap.example.org"
      baseDn="ou=people,dc=example,dc=org"
      ssl="true"
      userFilter="uid={0}";
*/
 
  // add a second *required* factor for YubiKey OTP validation
   com.yubico.jaas.YubikeyLoginModule required
      clientId="4711"
      id2name_textfile="/opt/shibboleth-idp/conf/yubikeys";
};

See https://github.com/Yubico/yubico-java-client/tree/master/jaas for all parameters and their use. Change the clientId to your "API key" provided by Yubico. As per get_username_for_id() from YubikeyToUserMapImpl.java the referenced id2name_textfile needs to contain a mapping from subject (i.e. "username" provided during authentication) to YubiKey public_id in the following format, one per line:

yk.<token-id>.user = <username>
yk.<token-id>.user = <username>
yk.<token-id>.user = <username>

All lines not starting with "yk." will be ignored, so could be used for comments, if needed.
Make sure the user your Java servlet container runs as has read permission for this file.

Logging configuration

 

In $IDP_HOME/conf/logging.xml, add logging configuration for the multi factor login handler :

<!-- ... -->
    <!-- Logs MultiAuth related messages -->
    <logger name="com.yubico.shibboleth" level="INFO" />
<!-- ... -->

And for the OATH OTP or YubiKey JAAS module:

<!-- ... -->
    <!-- Logs Yubico JAAS module(s) related messages -->
    <logger name="com.yubico.jaas" level="INFO" />
<!-- ... -->

Deployment

Backup your IdP configuration before re-deploying the IdP web app

 $IDP_INSTALL_DIR/install.sh

Known issues, bugs & comments

As indicated above, this login handler SHOULD ONLY be used when making the Yubi JAAS module "required". The IdP will send incorrect assertions otherwise, claiming the use of a Token when that has not been ensured.

Send bugs & comments to Klas Lindfors.