Yubikey est une clef de crypto qui permet d’avoir une authentification forte lors d’un processus de connexion à un site web (par ex : banque, web mail, etc….). Plusieurs sites web commencent à inclure cette fonctionnalité lors du processus d’authentification à leur service. L’utilisateur utilise un token généré par sa clef comme mot de passe. Ce mot de passe est aléatoire, est vérifié par le système et change à chaque utilisation. Si le mot de passe est intercepté par un tiers, ce dernier ne peut pas le rejouer pour s’authentifier.
But : Integration d’une authentification OTP via Yubico avec un serveur JBoss EAP.
Première étape : Le matériel
Pour cet exemple, les pré-requis suivants sont nécessaires :
- un clef Yubico (à commander ici)
- testé avec YubiKey NEO-n,
- cela doit fonctionner avec une YubiKey Nano ou YubiKey Neo
- une instance JBoss EAP ou Wildlfy
- testé avec instance EAP 6.3
- cela doit fonctionner avec toutes les versions JBoss EAP 6.X
- cela doit fonctionner avec les Wildfly 8+
Cet exemple utilise le service Yubico Cloud Service, le serveur doit pouvoir se connecter à Internet afin de valider le token OTP.
Deuxième étape : Compiler le client Yubico Java
Recupérer le code source yubico-java-client et le compiler :
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>
Vous allez recuperer deux JARs
Le premier JAR est le client au Cloud Yubico, le second est l’implementation du login module JAAS.
- Le client Yubico Cloud controle et verifie l’OTP fourni par la clef Yubico et retourne une validation.
- Client OTP Yubico OTP (protocole 2) : yubico-validation-client2-{Version}.jar
- Le login module Yubico fourni l’implementation à plugger dans le serveur JBoss, il va faire appel à l’Yubico Cloud via son client et son API.
- Module JAAS Yubico : yubico-jaas-module-{Version}.jar
Troisième étape: Creation du Module JBoss Yubico
JBoss ne propose pas par defaut de module Yubico, il faut le créer module.xml :
<?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>
Copier le ainsi que les jar dans le répertoire suivant :
$JBOSS_HOME/module/com/yubico/main
Ne pas oublier le copier le jar suivant, à récupérer de son cache maven après compilation :
edu.vt.middleware:vt-ldap:3.3.3
Tips : Pour mode debug rapide, faire un lien symbolique (Unix like seulement)
4ème étape : Get client Id & Secret Key for your JBoss Instance
Pour utiliser le Service Cloud Yubico, il est nécessaire de générer un Client Id et un Secret Key (ou aussi Client Key)
https://upgrade.yubico.com/getapikey/
–
Info utilisées en 7ème étape
5ème étape : Le PublicId des Yubico Key de vos utilisateurs
Chacun de vos utilisateurs doit vous fournir le PublicId de sa clef via la site suivant :
https://demo.yubico.com/start/otp/standard
–
Utiliser le champ Identity comme PublicId
6ème étape : Création de la correspondance entre le PublicId et le Login de l’utilisateur
Créer un fichier de correspondance entre le PublicId de l’utilisateur et son login, comme ceci :
greg@a.net> cat ${jboss.server.config.dir}/id2name_textfile.conf
yk.<PublicId>.user = <login>
Il s’agit d’une option au module JAAS Yubico pour authentifier l’utilisateur. Un utilisateur ne pourra pas utiliser une clef inconnue au système.
7ème étape : La configuration de l’instance JBoss
Création d’un security domaine dans le fichier standalone.xml.
<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>
On configure ensuite un module mapping pour récuperer les rôles de l’utilisateur. Il est bien sûr possible de changer via une autre source de données.
8ème étape : Configuration de l’application JAVA EE
Du pur standard JBoss, inclure le nom du security domain dans le fichier jboss-web.xml, comme suit :
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>yubico-auth</security-domain>
</jboss-web>
9ème étape : Création du mécanisme d’authentification
Dans la page de formulaire de login.
<form method='post' action='j_security_check'>
<input type='text' name='j_username'>
<input type='password' name='j_password'>
</form>
dans le fichier web.xml
<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 : Il est possible dans notre exemple de configurer le mode BASIC authentication.
10ème étape : Test et mode debug
Afin de contrôler le bon fonctionnement on passe en mode log verbeu
TRACE [org.jboss.as.web.security] Begin invoke, caller=null
DEBUG [org.apache.catalina.authenticator] Security checking request GET /form-auth/
DEBUG [org.apache.catalina.authenticator] Calling hasUserDataPermission()
DEBUG [org.apache.catalina.authenticator] Calling authenticate()
DEBUG [org.apache.catalina.authenticator] Save request in session 'bIbbT0CwH9ICDj-apERnL29O'
DEBUG [org.apache.catalina.authenticator] Failed authenticate() test
TRACE [org.jboss.as.web.security] End invoke, caller=null
TRACE [org.jboss.as.web.security] Begin invoke, caller=null
DEBUG [org.apache.catalina.authenticator] Security checking request POST /form-auth/j_security_check
DEBUG [org.apache.catalina.authenticator] Authenticating username '<LOGIN_USER>'
DEBUG [com.yubico.jaas.YubikeyLoginModule] Initializing YubikeyLoginModule
DEBUG [com.yubico.jaas.YubikeyLoginModule] Trying to instantiate com.yubico.jaas.impl.YubikeyToUserMapImpl
DEBUG [com.yubico.jaas.YubikeyLoginModule] Begin OTP login
TRACE [com.yubico.jaas.YubikeyLoginModule] Checking OTP <XXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY>
TRACE [com.yubico.jaas.YubikeyLoginModule] OTP <XXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY> verify result : OK
INFO [com.yubico.jaas.YubikeyLoginModule] OTP verified successfully (YubiKey id XXXXXXXXXXXX)
DEBUG [com.yubico.jaas.YubikeyLoginModule] Check if YubiKey XXXXXXXXXXXX belongs to user LOGIN_USER
TRACE [com.yubico.jaas.YubikeyLoginModule] In commit()
DEBUG [com.yubico.jaas.YubikeyLoginModule] Committing principal <YubikeyPrincipal>XXXXXXXXXXXX
TRACE [org.jboss.as.web.security] User: <LOGIN_USER> is authenticated
DEBUG [org.apache.catalina.authenticator] Authentication of '<LOGIN_USER>' was successful
DEBUG [org.apache.catalina.authenticator] Redirecting to original '/form-auth/'
DEBUG [org.apache.catalina.authenticator] Failed authenticate() test ??/form-auth/j_security_check
TRACE [org.jboss.as.web.security] End invoke, caller=null
TRACE [org.jboss.as.web.security] Begin invoke, caller=null
TRACE [org.jboss.as.web.security] Restoring principal info from cache
DEBUG [org.apache.catalina.authenticator] Security checking request GET /form-auth/
DEBUG [org.apache.catalina.authenticator] Calling hasUserDataPermission()
DEBUG [org.apache.catalina.authenticator] Calling authenticate()
DEBUG [org.apache.catalina.authenticator] Restore request from session 'bIbbT0CwH9ICDj-apERnL29O'
DEBUG [org.apache.catalina.authenticator] Authenticated '<LOGIN_USER>' with type 'FORM'
DEBUG [org.apache.catalina.authenticator] Proceed to restored request
DEBUG [org.apache.catalina.authenticator] Calling accessControl()
TRACE [org.jboss.as.web.security] hasRole:RealmBase says:true::Authz framework says:true:final=true
TRACE [org.jboss.as.web.security] hasResourcePermission:RealmBase says:true::Authz framework says:true:final=true
DEBUG [org.apache.catalina.authenticator] Successfully passed all security constraints
TRACE [org.jboss.as.web.security] End invoke, caller=null
Dans les traces, on retrouve les principales informations de l’utilisateur :
<LOGIN_USER> : the login user
XXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY : the OTP sent to Yubico Cloud Service
XXXXXXXXXXXX : the Public Id, the Yubico key user