Multi Factor Login Handler
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
- You can read about how JAAS works at http://download.oracle.com/javase/1.5.0/docs/api/javax/security/auth/login/Configuration.html
- Multi factor JAAS is similar to UsernamePassword JAAS
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)
- Set up an OATH-HOTP basic auth protected web page somewhere using the Apache mod_authn_otp.
See this page for more details.
<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 cnofiguredjaasConfigName
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-usinglogin.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.