Yubico key (https://www.yubico.com/) is a really smart key to get a strong authentication to login into your e-account (e-bank, web mail, etc...). Even if an hacker can intercept password, he can't re use it to login cause password is one time only. Password is provided by the key and changes every time. Several e-companies includes/are including this features to login to enforce security.
Goal : an example to integrate Yubico OTP (On Time Password : http://en.wikipedia.org/wiki/One-time_password) into JBoss EAP via Yubico JAAS Login Module.
for 2AF please follow : Two Factor Authen. (2FA) w/ Yubico OTP and JBoss EAP 6 or Wildfly 8
First step : Materials
For this example you need several materials :
- an Yubico key (you can buy one https://store.yubico.com/)
- tested with YubiKey NEO-n,
- should work with YubiKey Nano and YubiKey Neo
- a JBoss EAP or Wildlfy instance (http://www.redhat.com/en or http://www.wildfly.org/)
- tested with EAP 6.3
- should work with all JBoss EAP 6.X
- should work with all JBoss AS 7.X or Wildfly 8+
This example will check and control the OTP with Yubico Cloud Service, the JBoss instance needs an acces to Internet (HTTP/HTTPS)
Second step : Compile Yubico Java Client
Retrieve the yubico-java-client source code and compile it
greg@a.net> git clone git@github.com:Yubico/yubico-java-client.git greg@a.net> cd yubico-java-client greg@a.net> mvn clean package .... OMIT ..... [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] [INFO] Yubico OTP validation client ....................... SUCCESS [ 0.003 s] [INFO] Yubico OTP validation client protocol 1 ............ SUCCESS [ 2.254 s] [INFO] Yubico OTP validation client protocol 2 ............ SUCCESS [ 3.798 s] [INFO] Yubico JAAS module ................................. SUCCESS [ 0.710 s] [INFO] yubico-demo-server ................................. SUCCESS [ 2.782 s] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 9.704 s [INFO] Finished at: 2015-03-01T16:42:11+01:00 [INFO] Final Memory: 39M/228M [INFO] ------------------------------------------------------------------------ greg@a.net>
You should get several outputs JAR
the first one is the yubico cloud client and the second one is the Yubico login module (Yubico JAAS Impl)
- Yubico cloud client will control and check the OTP provided by the Yubico Key and will return the authorization.
- Yubico OTP validation client protocol 2 : yubico-validation-client2-<Version>.jar
- Yubico login module provides a Login module implementation to plug into an application or an application server using JAAS API.
- Yubico JAAS module : yubico-jaas-module-<Version>.jar
Third step : Create Yubico JBoss Module
Create an module.xml file
<?xml version="1.0" encoding="UTF-8"?> <!-- ~ JBoss, Home of Professional Open Source. ~ Copyright 2014, Red Hat, Inc., and individual contributors ~ as indicated by the @author tags. See the copyright.txt file in the ~ distribution for a full listing of individual contributors. ~ ~ This is free software; you can redistribute it and/or modify it ~ under the terms of the GNU Lesser General Public License as ~ published by the Free Software Foundation; either version 2.1 of ~ the License, or (at your option) any later version. ~ ~ This software is distributed in the hope that it will be useful, ~ but WITHOUT ANY WARRANTY; without even the implied warranty of ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ~ Lesser General Public License for more details. ~ ~ You should have received a copy of the GNU Lesser General Public ~ License along with this software; if not, write to the Free ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org. --> <module xmlns="urn:jboss:module:1.1" name="com.yubico"> <resources> <resource-root path="yubico-jaas-module-3.0.0-SNAPSHOT.jar"/> <resource-root path="yubico-validation-client2-3.0.0-SNAPSHOT.jar"/> <resource-root path="vt-ldap-3.3.3.jar"/> </resources> <dependencies> <module name="org.picketbox"/> <module name="javax.api"/> <module name="org.slf4j"/> <module name="org.apache.commons.codec" /> <module name="javax.security.jacc.api" /> <!-- for a future propose --> <module name="javax.servlet.api"/> <!-- for a future propose --> <module name="org.jboss.common-core"/> <!-- for a future propose --> </dependencies> </module>
Copy it and jars too into your JBoss Module directory.
$JBOSS_HOME/module/com/yubico/main
NB don't forget to copy this jar into the directory, pick up directly from you .m2 repository
edu.vt.middleware:vt-ldap:3.3.3
Tips : to debug quickly, you can create symbolic link
4th step : Get client Id & Secret Key for your JBoss Instance
To use the Yubico Cloud Service you need to get your own Client Id and Secret Key (aka client Key)
https://upgrade.yubico.com/getapikey/
Useful for 7th step
5th step : Get PublicId of you Yubico Key
For each of your clients have to provide theirs own PublicId to you
https://demo.yubico.com/start/otp/standard
Use the Identity field as <PublicId>
6th step : Create PublicId --> Login User mapping file
Create a mapping file with all previous PublicId and Login user
greg@a.net> cat ${jboss.server.config.dir}/id2name_textfile.conf yk.<PublicId>.user = <login>
We use this Yubico JAAS option to authenticate the Yubico key with the User Login. An user with an unknown Yubikey Id cannot logon.
7th step : Configure your JBoss Instance Security Domain
Create a new security domain
<security-domain name="yubico-auth" cache-type="default"> <authentication> <login-module code="com.yubico.jaas.YubikeyLoginModule" flag="required" module="com.yubico"> <module-option name="clientId" value="12123"/> <module-option name="clientKey" value="U873jhsYT629uuh7gban65+p2Io="/> <!-- client Key aka secret Key --> <module-option name="id2name_textfile" value="${jboss.server.config.dir}/id2name_textfile.conf"/> </login-module> </authentication> <mapping> <mapping-module code="SimpleRoles" type="role"> <!-- for example only --> <module-option name="<PublicId>" value="manager"/> </mapping-module> </mapping> </security-domain>
we have to create an mapping module to retrieve all user roles, for this example we use SimpleRoles but you can change it to retrieve from an other data source.
8th step : Configure your application to use yubico-auth
to use the previous "yubico-auth" inject it into your jboss-web.xml
<?xml version="1.0" encoding="UTF-8"?> <jboss-web> <security-domain>yubico-auth</security-domain> </jboss-web>
9th step : Use the Form Auth mechanism
Into your login page
<form method='post' action='j_security_check'> <input type='text' name='j_username'> <input type='password' name='j_password'> </form>
into your web.xml file
<web-app> <security-constraint> <web-resource-collection> <web-resource-name>User Auth</web-resource-name> <url-pattern>/auth/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> <role-name>manager</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>FORM</auth-method> <realm-name>User Auth</realm-name> <form-login-config> <form-login-page>login.jsp</form-login-page> <form-error-page>error.jsp</form-error-page> </form-login-config> </login-config> <security-role> <role-name>admin</role-name> </security-role> <security-role> <role-name>manager</role-name> </security-role> </web-app>
NB : BASIC authentication should work without problem. Remove form login config stuff and change auth-method to BASIC
10th step : Enjoy It & Debug authentication log to check the configuration
18:32:54,396 TRACE [org.jboss.as.web.security] (http-/127.0.0.1:8080-1) Begin invoke, caller=null 18:32:54,403 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Security checking request GET /form-auth/ 18:32:54,404 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Calling hasUserDataPermission() 18:32:54,404 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Calling authenticate() 18:32:54,412 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Save request in session 'bIbbT0CwH9ICDj-apERnL29O' 18:32:54,461 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Failed authenticate() test 18:32:54,462 TRACE [org.jboss.as.web.security] (http-/127.0.0.1:8080-1) End invoke, caller=null 18:32:59,880 TRACE [org.jboss.as.web.security] (http-/127.0.0.1:8080-1) Begin invoke, caller=null 18:32:59,880 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Security checking request POST /form-auth/j_security_check 18:32:59,881 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Authenticating username '<LOGIN_USER>' 18:32:59,906 DEBUG [com.yubico.jaas.YubikeyLoginModule] (http-/127.0.0.1:8080-1) Initializing YubikeyLoginModule 18:32:59,916 DEBUG [com.yubico.jaas.YubikeyLoginModule] (http-/127.0.0.1:8080-1) Trying to instantiate com.yubico.jaas.impl.YubikeyToUserMapImpl 18:32:59,919 DEBUG [com.yubico.jaas.YubikeyLoginModule] (http-/127.0.0.1:8080-1) Begin OTP login 18:32:59,927 TRACE [com.yubico.jaas.YubikeyLoginModule] (http-/127.0.0.1:8080-1) Checking OTP <XXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY> 18:33:01,134 TRACE [com.yubico.jaas.YubikeyLoginModule] (http-/127.0.0.1:8080-1) OTP <XXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY> verify result : OK 18:33:01,134 INFO [com.yubico.jaas.YubikeyLoginModule] (http-/127.0.0.1:8080-1) OTP verified successfully (YubiKey id XXXXXXXXXXXX) 18:33:01,134 DEBUG [com.yubico.jaas.YubikeyLoginModule] (http-/127.0.0.1:8080-1) Check if YubiKey XXXXXXXXXXXX belongs to user LOGIN_USER 18:33:01,137 TRACE [com.yubico.jaas.YubikeyLoginModule] (http-/127.0.0.1:8080-1) In commit() 18:33:01,137 DEBUG [com.yubico.jaas.YubikeyLoginModule] (http-/127.0.0.1:8080-1) Committing principal <YubikeyPrincipal>XXXXXXXXXXXX 18:33:01,140 TRACE [org.jboss.as.web.security] (http-/127.0.0.1:8080-1) User: <LOGIN_USER> is authenticated 18:33:01,148 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Authentication of '<LOGIN_USER>' was successful 18:33:01,148 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Redirecting to original '/form-auth/' 18:33:01,148 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Failed authenticate() test ??/form-auth/j_security_check 18:33:01,148 TRACE [org.jboss.as.web.security] (http-/127.0.0.1:8080-1) End invoke, caller=null 18:33:01,151 TRACE [org.jboss.as.web.security] (http-/127.0.0.1:8080-1) Begin invoke, caller=null 18:33:01,151 TRACE [org.jboss.as.web.security] (http-/127.0.0.1:8080-1) Restoring principal info from cache 18:33:01,151 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Security checking request GET /form-auth/ 18:33:01,151 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Calling hasUserDataPermission() 18:33:01,151 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Calling authenticate() 18:33:01,151 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Restore request from session 'bIbbT0CwH9ICDj-apERnL29O' 18:33:01,151 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Authenticated '<LOGIN_USER>' with type 'FORM' 18:33:01,152 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Proceed to restored request 18:33:01,152 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Calling accessControl() 18:33:01,152 TRACE [org.jboss.as.web.security] (http-/127.0.0.1:8080-1) hasRole:RealmBase says:true::Authz framework says:true:final=true 18:33:01,152 TRACE [org.jboss.as.web.security] (http-/127.0.0.1:8080-1) hasResourcePermission:RealmBase says:true::Authz framework says:true:final=true 18:33:01,152 DEBUG [org.apache.catalina.authenticator] (http-/127.0.0.1:8080-1) Successfully passed all security constraints 18:33:01,155 TRACE [org.jboss.as.web.security] (http-/127.0.0.1:8080-1) End invoke, caller=null
Into the log trace you can notice severals useful informations :
- <LOGIN_USER> : the login user
- XXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY : the OTP sent to Yubico Cloud Service
- XXXXXXXXXXXX : the Public Id, the Yubico key user
Useful links :
- French version : Yubico OTP et JBoss EAP 6 ou Wildfly 8
- http://yubico.github.io/yubico-java-client/
- yubico-java-client/jaas at master · Yubico/yubico-java-client · GitHub
- Authentication Modules - JBoss AS 7.0 - Project Documentation Editor
- JBoss AS7: Security : Custom Login Modules
- http://java.dzone.com/articles/creating-custom-login-modules