Yubico OTP and JBoss EAP 6 or Wildfly 8

Version 7

    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 :

     

    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/

     

    Capture d’écran 2015-03-01 à 16.23.49.png

     

    Capture d’écran 2015-03-01 à 16.11.02.png

    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

     

     

    Capture d’écran 2015-03-01 à 16.13.12.png

     

    Capture d’écran 2015-03-01 à 16.07.53.png

    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 :