JBoss autenticación basada en certificados cliente.
1. Introducción
La autenticación usando certificado cliente es uno de los métodos que podemos utiilizar para autenticar a una persona en el entorno web. Está ampliamente difundido en las aplicaciones de la administración pública: la aplicación para realizar la declaración de la renta de la Agencia Tributaria y la empleada para consultar los puntos de nuestro carnet, de la Dirección General de Tráfico son las más famosas.
Los servidores de aplicación, como JBoss, ofrecen la posibilidad de aplicar este tipo de autenticación de una forma muy sencilla. A pesar de la simplicidad en la configuración hay que tener muy claro los conceptos y pasos a seguir, haciendo hincapié en los certificados y demás configuración alrededor de ellos.
Con este tutorial veremos paso a paso el proceso para que nuestra aplicación utilice este tipo de autenticación, desde la generación de certificados hasta la configuración de nuestra aplicación web.
2. Entorno
Entorno utilizado para escribir este tutorial:
- Hardware: Mac Book Pro (Core 2 Duo 2,8 Ghz, 4 GB RAM, 500 GB)
- Sistema Operativo: Snow Leopard 10.6.5
- JBoss: 6.0M5
- OpenSSL: 0.9.8
- keytool: JDK 1.6.0
3. Generación de certificados
La autenticación con certificado cliente requiere obligatoriamente una conexión segura (HTTPS) y la creación de un conjunto de certificados x509. En nuestro caso debemos generar un certificado para el servidor y otro para el cliente y además ambos deberán estar firmados por una entidad de certificación (CA) válida.
Debido a que la firma de nuestros certificados por una entidad de certificación válida implica realizar un desembolso económico, vamos a crearnos nuestra propia CA con la que firmaremos los certificados cliente/servidor. Esto implica, como veremos más adelante, que tengamos que añadir el certificado de la CA en nuestros almacenes de certificados de confianza para que la aplicación web funcione adecuadamente.
3.1. Generación del certificado de la CA
OpenSSL es la herramienta que vamos a utilizar para trabajar con los certificados. Lo primero que tenemos que hacer es generar una clave privada RSA que utilizaremos para generar todos los certificados.
openssl genrsa -des3 -out ca_tutorial.key 4096
Con este comando le decimos a openssl que queremos generar una clave rsa con el nombre ca_tutorial.key de 4096 bytes y que el algoritmo para encriptar la password será TripleDes. En el proceso de generación de la clave privada, se nos preguntará por una contraseña en nuestro caso podremos «autentia2010».
Una vez creada la clave privada ya podemos generar el certificado de la CA:
openssl req -x509 -days 365 -new -key ca_tutorial.key -out ca_tutorial.crt Enter pass phrase for ca_tutorial.key: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:ES State or Province Name (full name) [Some-State]:Madrid Locality Name (eg, city) []:Madrid Organization Name (eg, company) [Internet Widgits Pty Ltd]:Autentia Organizational Unit Name (eg, section) []:Developer Common Name (eg, YOUR name) []:Autentia CA Email Address []:
Como podemos ver se nos pedirá la contraseña de la clave y posteriormente debemos responder a una serie de preguntas: Nombre del país, provincia, localidad, etc…
Si ahora abrimos el certificado (en nuestro caso con la aplicación «Acceso a llaveros») veremos algo como:
3.2. Generación del certificado de servidor para JBoss
Una vez que tenemos el certificado de la CA tenemos que crear el certificado que utilizará nuestro servidor para las conexiones por HTTPS. Esta vez tenemos que generar una «Petición de certificado» que más tarde deberá ser firmada por la CA creada anteriormente.
Utilizando la clave privada ca_tutorial.key generamos el fichero CSR (Certificate Signed Request):
openssl req -new -key ca_tutorial.key -out jboss.csr Enter pass phrase for ca_tutorial.key: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:ES State or Province Name (full name) [Some-State]:Madrid Locality Name (eg, city) []:Madrid Organization Name (eg, company) [Internet Widgits Pty Ltd]:Autentia Organizational Unit Name (eg, section) []:Developer Common Name (eg, YOUR name) []:localhost Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:autentia2010 An optional company name []:Autentia
Hay que tener sumo cuidado con el valor de la propiedad Common Name. El valor deberá coincidir con el dominio de nuestra aplicación de lo contrario el navegador no confiará en él. En nuestro caso el valor sería «localhost».
Ahora tenemos que generar un certificado x509 firmarlo por la CA:
openssl x509 -req -days 365 -in jboss.csr -CA ca_tutorial.crt -CAkey ca_tutorial.key -set_serial 01 -out jboss.crt
El parámetro set_serial se incrementará según la CA vaya firmando certificados, es decir, el siguiente certificado firmado que se cree set_serial tendrá el valor 02 y así sucesivamente.
3.3. Crear el certificado cliente
Para poder probar el funcionamiento de la aplicación con este tipo de autenticación debemos crear un certificado cliente. De la misma forma que para el certificado del servidor tendremos que generar un fichero CSR y firmado por la CA.
Generamos el fichero CSR del cliente:
openssl req -new -key ca_tutorial.key -out cliente.csr Enter pass phrase for ca_tutorial.key: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:ES State or Province Name (full name) [Some-State]:Madrid Locality Name (eg, city) []:Madrid Organization Name (eg, company) [Internet Widgits Pty Ltd]:Autentia Organizational Unit Name (eg, section) []:Developer Common Name (eg, YOUR name) []:Angel Garcia Email Address []:angel.garcia@autentia.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:autentia2010 An optional company name []:
Y ahora lo firmamos:
openssl x509 -req -days 365 -in cliente.csr -CA ca_tutorial.crt -CAkey ca_tutorial.key -set_serial 02 -out cliente.crt
4. Configurando JBoss
Ahora que ya tenemos todos los certificados nos toca configurar JBoss. Lo primero será habilitar la conexión por HTTPS. Para ello, tenemos que crear una almacén de claves y un almacén de certificados en los que confiará nuestro servidor para validar los certificados cliente.
4.1. Creación del almacén de claves
Para crear el almacén de claves es necesario primero convertir el certificado jboss.crt al formato PCKS12. Ejecutamos:
openssl pkcs12 -export -inkey ca_tutorial.key -in jboss.crt -out jboss.pkcs12
Y a continuación creamos el almacen con la herramienta keytool que viene con la JDK:
keytool -importkeystore -destkeystore jboss.keystore -srckeystore jboss.pkcs12 -srcstoretype PKCS12
Únicamente tendremos que tener en cuenta que la contraseña del almacén de claves deberá ser la misma que la de la key generada anteriormente.
4.2. Creación del almacén de certificados
Ahora tenemos que crear el almacén de certificados que utilizará JBoss para validar los certificados clientes. En nuestro caso el almacén sólo tendrá el certificado de la CA generada.
keytool -importcert -alias "Autentia CA" -file ca_tutorial.crt -keystore jboss.truststore Escriba la contraseña del almacén de claves: Volver a escribir la contraseña nueva: Propietario: CN=Autentia CA, OU=Developer, O=Autentia, L=Madrid, ST=Madrid, C=ES Emisor: CN=Autentia CA, OU=Developer, O=Autentia, L=Madrid, ST=Madrid, C=ES Número de serie: 9b5b03fd9dfa86ba Válido desde: Wed Nov 24 09:43:54 CET 2010 hasta: Thu Nov 24 09:43:54 CET 2011 Huellas digitales del certificado: MD5: F8:4B:D2:77:C8:40:40:CD:00:8D:A4:B2:BC:11:3A:B4 SHA1: 7E:12:28:89:14:14:13:B8:6F:79:4E:BC:14:15:73:CF:C0:58:1A:BE Nombre del algoritmo de firma: SHA1withRSA Versión: 3 ¿Confiar en este certificado? [no]: y Se ha añadido el certificado al almacén de claves
4.3. Habilitando HTTPS en JBoss
En nuestro ejemplo vamos a arrancar con la configuración «default». Primero copiamos jboss.keystore y jboss.truststore al directorio «$JBOSS_HOME/server/default/conf».
Una vez copiados tendremos que editar el fichero server.xml dentro del directorio «$JBOSS_HOME/server/default/deploy/jbossweb.sar y añadir las siguientes líneas:
4.4. Habilitando la autenticación de certificados cliente con JAAS en JBoss
Para poder utilizar la autenticación de certificado cliente en JBoss tenemos que tocar los ficheros legacy-conf-service.xml y login-config.xml situados en «$JBOSS_HOME/server/default/deploy» y «$JBOSS_HOME/server/default/conf», respectivamente. En ellos definiremos todo lo necesario para poder utilizar JAAS en nuestras aplicaciones.
Primero tenemos que añadir un MBean a legacy-conf-service.xml encargado de acceder al almacén de claves y necesario en uno de los módulos que configuremos en login.config.xml. Para acceder a él debemos hacerlo por RMI «java:/jaas/domainweb».
${jboss.server.home.dir}/conf/jboss.keystore autentia2010
En el fichero login-config.xml se define la política de autenticación de nuestras aplicaciones web, es decir, los módulos que serán utilizados en el proceso de autenticación y autorización de las aplicaciones.
Para nuestro ejemplo, JBoss dispone del módulo BaseCertLoginModule para aplicar una autenticación basada en certificado cliente o comúnmente llamada CLIENT-CERT y el módulo UsersRolesLoginModule para el proceso de autorización.
Estas son las líneas que deberíamos añadir a login-config.xml.
useFirstPass java:/jaas/domainweb useFirstPass domainweb-users.properties domainweb-roles.properties
De estas líneas podemos destacar el nombre de la política de seguridad «domainweb» que posteriormente deberemos usar en la configuración de la aplicación web, la opción securityDomain del módulo BaseCertLoginModule donde le indicamos la ruta de acceso al MBean del Dominio de Seguridad creado anteriormente y los ficheros de propiedades donde se encuentran definidos los usuarios y roles de la aplicación. Estos dos ficheros los vamos a crear en la aplicación web.
Para que el cliente pueda conectarse a la aplicación necesitamos que el certificado se encuentre almacenado en el almacén de claves que lee el Dominio de Seguridad, y es muy importante que el alias con el que se almacene el certificado corresponda con el DN del certificado. Para conocer el DN tendremos que ejecutar el siguiente comando:
keytool -printcert -file cliente.crt Propietario: EMAILADDRESS=angel.garcia@autentia.com, CN=Angel Garcia, OU=Developer, O=Autentia, L=Madrid, ST=Madrid, C=ES Emisor: CN=Autentia CA, OU=Developer, O=Autentia, L=Madrid, ST=Madrid, C=ES Número de serie: 2 Válido desde: Wed Nov 24 09:59:26 CET 2010 hasta: Thu Nov 24 09:59:26 CET 2011 Huellas digitales del certificado: MD5: 4C:6C:05:02:8E:1B:93:12:8D:1D:0B:2C:05:B6:39:EB SHA1: 79:CA:45:98:7D:92:87:64:A3:E2:2C:FD:F5:3C:FC:62:6A:F4:50:B5 Nombre del algoritmo de firma: SHA1withRSA Versión: 1
El valor del alias seria el del campo Propietario. Ahora para añadir el certificado a jboss.keystore ejecutamos:
keytool -importcert -alias "EMAILADDRESS=angel.garcia@autentia.com, CN=Angel Garcia, OU=Developer, O=Autentia, L=Madrid, ST=Madrid, C=ES" -file cliente.crt -keystore jboss.keystore
5. Creando la aplicación web
El siguiente paso es crear una aplicación web que utilice el dominio de seguridad creado en el apartado anterior. Con eclipse creamos un proyecto DynamicWeb y le añadimos dos recursos index.html y certificado/index.html bajo la carpeta WebContent.
Ahora vamos a configurar la aplicación web para que cuando se acceda a los recursos situados dentro del directorio «certificado» pida al usuario un certificado cliente mientras que el resto de recursos serán públicos.
En el fichero web.xml añadimos:
Autenticacion con certificados /certificado/* GET POST User User CLIENT-CERT Autenticación con Certificado Cliente
Con estas líneas le indicamos a JBoss que todos los recursos que se encuentren en /certificado estarán protegidos. ¿Cómo se hace esto?, con la etiqueta security-constraint indicándole el patrón de url de los recursos que están protegidos. Luego con la etiqueta login-config le indicamos el método de autenticación basado en certificado cliente «CLIENT-CERT».
Ahora creamos un fichero específico para JBoss donde le configuramos el dominio de seguridad que utilizará la aplicación. Creamos un fichero jboss-web.xml en el directorio WEB-INF de nuestra aplicación con:
java:/jaas/domainweb autentia
Y por último añadimos a src los ficheros de propiedades domainweb-users.properties y domainweb-roles.properties. Sólo nos quedaría añadir al fichero domainweb-roles.properties el rol que va a tener nuestro usuario cliente. Recordad que los iguales y espacios deben ser escapados con \.
EMAILADDRESS\=angel.garcia@autentia.com,\ CN\=Angel\ Garcia,\ OU\=Developer,\ O\=Autentia,\ L\=Madrid,\ ST\=Madrid,\ C\=ES=User
Creamos el fichero WAR y los depositamos en $JBOSS_HOME/server/default/deploy.
Si ahora accedemos con un navegador a http://localhost:8443/autentia/certificado/index.html. Nos deberá salir:
En cambio si accedemos a http://localhost:8443/autentia/index.html, JBoss, no nos pedirá ningún certificado.
6. Añadiendo el certificado cliente al Navegador.
Para el acceso a la aplicación utilizaremos Firefox. Debido a que sólo importa certificados con el formato PCKS12 tendremos que convertir el fichero cliente.crt a este formato. Para ello ejecutamos:
openssl pkcs12 -export -in cliente.crt -inkey ca_tutorial.key -out cliente.pcks12
Después de convertir el certificado, abrimos Firefox, y nos vamos a las «Preferencias» -> «Avanzado» -> «Ver certificados». Nos muestra una ventana modal con el almacén de certificados que utiliza Firefox. Ahora nos vamos a la pestaña «Sus certificados» y pichamos en «Importar». Seleccionamos el fichero cliente.pkcs12, pulsamos «Aceptar» e introducimos la contraseña de la clave utilizada en el certificado del cliente.
Si todo ha ido bien nos saldrá algo como:
De la misma forma que para el servidor JBoss, debemos añadir al almacén de nuestro navegador el certificado de la CA para confiar en todas las conexiones seguras cuyos certificados estén firmados por esta CA. Como hicimos con el certificado cliente, nos vamos a «Preferencias» -> «Avanzado» -> «Cifrado» -> «Ver certificados» -> «Autoridades» y pulsamos «Importar». Seleccionamos el certificado ca_tutorial.crt» y damos aceptar (aceptando todas las opciones de confianza).
Ahora sólo nos queda acceder de nuevo a http://localhost:8443/autentia/certificado/index.html. Si todo ha ido bien nos saldrá una pantalla en el que debemos elegir el certificado que vamos a enviar al servidor. Damos aceptar y vualá!!! tenemos acceso al recurso.
7. Conclusiones
Como habéis podido leer, configurar la autenticación basada en certificado cliente es sencillo pero hay que tener muy claro lo que estamos haciendo en cada momento para llegar a buen puerto. Desde Autentia recomendamos utilizar cuando sea posible los servicios que los servidores de aplicaciones nos ofrecen no sólo para ahorrar tiempo de desarrollo sino para reducir la complejidad de nuestra aplicaciones.
Hola Ángel, enhorabuena por el tutorial, está muy bien en contenidos y presentación. Perfecto.
Te seguiré en más tutoriales…. a ver si logro seguirte el ritmo que veo que llevas un nivel muy alto 😉
Buen Día,
Muchas gracias por tu tutorial, me parecio una guía muy buena. He seguido todos los pasos, pero cuando intento acceder a mi pagina, y ya agregando los certificados al navegador, me encuentro con el siguiente error: 🙁
Estado HTTP 400 – No hay cadena de certificados del cliente en esta petición.
Hola Rastu,
Ese error lo da cuando el navegador no esta enviando un certificado del cliente. Asegurate que hayas realizado todos los pasos en el navegador.
Hola Angel,
Muchas Gracias por tu respuesta. He estado revisando,
haciendo los pasos uno a uno, generando los certificados,
y ahora obtengo el siguiente error
Estado HTTP 401 – Imposible autenticar mediante las credenciales suministradas.
HTTP 401 – Imposible autenticar mediante las credenciales suministradas
https://localhost:5000/TestSSL/certificado/index.html
No sé que estoy haciendo mal, he cargado el certificado cliente y el que autoriza a los navegadores y aún así no funciona.
Yo lo unico que hice diferente fue copiar el jboss.keystore, a la carpeta conf de jboss, después de que se agregara el alias. En los pasos no dicen eso, pero supuse porque no entendía para que se copiaba el jboss.keystore en la carpeta conf del jboss, y despues se hacía esto.
El valor del alias seria el del campo Propietario. Ahora para añadir el certificado a jboss.keystore ejecutamos:
que el paso anterior al 5
cuando realizan
keytool -importcert -alias \\\»EMAILADDRESS=angel.garcia@autentia.com, CN=Angel Garcia, OU=Developer, O=Autentia, L=Madrid, ST=Madrid, C=ES\\\» -file cliente.crt -keystore jboss.keystore
Agradezco cualquier tipo de ayuda!!! Muchas Gracias ANgel
Buen Día,
El tutorial está perfecto! El problema que se me presentaba era por el versionamiento del JBOSS.(Estaba manejando Jboss 4.2.3). De todas formas, cuando encuentre la configuración para dicha versión del Jboss, les comentaré.
Un saludo
Salu2 Angel,
Bueno el paper, si se sigue paso a paso es entendible, la instalación del vcredist_x64 un poco molesta como prerrequisito del Win64OpenSSL-0_9_8x.
En cuanto a la configuración solo la dejé /* para todos los recursos en el web.xml. Los properties los dejé en el conf/ del server, también cambié el rol.
Hay que tener cuidado con el certificado ya que bloquea otras aplicaciones que no estén en el dominio configurado en el cliente.crt
Oye no entiendo esta parte:
«Y por último añadimos a src los ficheros de propiedades domainweb-users.properties y domainweb-roles.properties. Sólo nos quedaría añadir al fichero domainweb-roles.properties el rol que va a tener nuestro usuario cliente.»
¿De donde salen esos properties y que estructura deben tener?
¿En donde se encuentra el «src»?
Hola David,
El contenido de domainweb-users.properties lo tienes en el tutorial. En este fichero tendrás que añadir todos los usuario que tendrán permisos para acceder a la aplicación. Corresponden al alias/propietario del certificado cliente del usuario. En el tutorial corresponde a:
EMAILADDRESS=angel.garcia@autentia.com, CN=Angel Garcia, OU=Developer, O=Autentia, L=Madrid, ST=Madrid, C=ES
En el caso de domainweb-roles.properties. En este tendrás que poner los roles que tendrá cada usuario dado de alta en domainweb-users.properties en tu aplicación. El fichero quedaría una cosa así:
EMAILADDRESS=angel.garcia@autentia.com, CN=Angel Garcia, OU=Developer, O=Autentia, L=Madrid, ST=Madrid, C=ES=USER,ADMIN,DEVELOPER
Espero haberte ayudado.