Autentificación y Autorización mediante JAAS

Autentificación y Autorización mediante JAAS

Normalmente, casi todas las aplicaciones o sistemas necesitan de los procesos de autentificación y autorización. En este tutorial, vamos a realizar un completo ejemplo de autentificación de usuarios así como realizar un control de las posibles acciones que pueden realizar en función de su identidad. Para ello vamos a basarnos en el estándar de seguridad Java pensado para estas tareas, es decir, vamos a hacer uso de JAAS.

En este tutorial vamos a realizar un completo ejemplo a través del cual dos usuarios podrán logarse y tendrán distintos privilegios en función de quien sea.

Índice de contenido

Un poco de teoría: Introducción a JAAS

JAAS son las siglas de Java Authentication and Authorization. Se trata de una especificación integrada en la máquina virtual Java a partir de la versión 1.4 y cuya finalidad es la de definir un estándar para los procesos de autentificación y autorización.

Es decir ambos procesos, autentificación y autorización están directamente relacionados con la seguridad de aplicaciones.

¿Qué es la autentificación?

La autentificación es el proceso por el cual un usuario o servicio tiene que autentificarse para poder acceder a ciertos servicios que ofrece nuestro sistema.

Existen distintas categorías de autentificación:

  • ¿Qué sabes?: Información que el usuario conoce, ejemplos: contraseñas, respuestas a preguntas como: “dni de la abuela”
  • ¿Qué tienes?: Elementos físicos que el usuario posee, como por ejemplo una determinada tarjeta.
  • ¿Quién eres?: Técnicas biométricas como lectura de retina o huellas dactilares.

¿Qué es la autorización?

La autorización es el proceso por el cual se controlan las acciones que tiene un usuario o servicio normalmente ya autenticado puede realizar, para ello se le conceden o deniegan permisos.

En Java, aunque muchos libros lo dicen, no es del todo cierto que el proceso de autorización implique que el usuario previamente haya sido autentificado. Digo esto, porque en Java se pueden definir permisos en base a otros parámetros como por ejemplo a nivel de “quién firma el código a ejecutar” (opción SignedBy de la configuración de privilegios) o “En qué JAR está el código a ejecutar” (opción CodeBase de la configuración de privilegios).

Categorías de autorización:

  • Autorización declarativa: En este tipo de autorización los privilegios son gestionados un administrador independientemente de manera externa al código de la aplicación
  • Autorización programática: En este tipo de autorización las decisiones de autorización se realizan desde el código fuente de la aplicación.

¿Por qué es bueno que use JAAS en mis aplicaciones en vez de realizar yo mismo ese control?

Al tratarse de una especificación estándar, hay muchas implementaciones disponibles dándote entre otros los siguientes beneficios:

  • Ahorrarás tiempo y dinero, pues podrás usar la implementación que más se asemeje a tus necesidades.
  • La especificación está documentada y al ser estándar encontrará más fácilmente personal que tenga conocimientos sobre el tema.
  • Cambiar una implementación por otra, puede ser tan sencillo como cambiar el archivo de configuración.
  • Aprovecharse de las nuevas versiones que vayan saliendo, sin invertir dinero en su desarrollo.
  • Etc.

Comprender JAAS a través de un completo ejemplo.

En este tutorial vamos a realizar un completo ejemplo a través del cual dos usuarios podrán logarse y tendrán distintos privilegios en función de quién sea.

  • El usuario1 tendrá privilegios para ver un determinado directorio y para crear un socket que se conecte al puerto 80 del dominio autentia.com.
  • El usuario2 tendrá privilegios para ver un determinado directorio, pero no podrá crear un socket que se conecte al puerto 80 del dominio autentia.com.

Para ello, realizaremos las siguientes cosas:
  • Crearemos los archivos de configuración de autentificación y autorización
  • Implementar un javax.security.auth.spi.LoginModule que permita autentificar usuarios solicitando para ellos un usuario y un password.
  • Implementar un javax.security.auth.callback.CallbackHandler que solicite al usuario su login y el contraseña.
  • Implementar un java.security.Principal que represente la identidad de los usuarios.

Salidas generadas por la aplicación

Antes de comenzar a ver el código de la aplicación, pienso que es interesante que vea las diferentes salidas que generará la aplicación al ser ejecutada.

Salida generada al ejecutar la aplicación logándonos incorrectamente:

Salida generada al ejecutar la aplicación logándonos correctamente como usuario1:

Salida generada al ejecutar la aplicación logándonos correctamente como usuario2:

Autentificación JAAS: Archivo de configuración del Módulo de Login (login.conf)

Aunque existen varios módulos de Login ya implementados: Solaris Login Module, NT Login Module, JNDI Login Module…, nosotros vamos a realizar el nuestro teniendo en mente que luego sustituirlo por otro, desde el punto de vista de nuestra aplicación, es tan fácil como cambiar la configuración (y por supuesto aprender a configurar el otro leyendo su documentación).

Observe como se integra con el resto de componentes:

  • Fijese en la línea 24 del código de la aplicación JAAS_App que se muestra más abajo.
  • Fijese en la línea 3 del archivo de configuración de autorización (policy.jaas) que se muestra más abajo.

Autorización JAAS: Archivo de configuración (policy.jaas)

Ahora definimos los permisos que tiene nuestra aplicación a través de un archivo de configuración.
Existen otras muchas formas de definir estos permisos (por ejemplo, BD), pero nosotros usaremos esta forma por defecto.

Nota: Si observa el archivo <JRE_HOME>/lib/security/security.policy verá una línea como está: login.configuration.provider=com.sun.security.auth.login.ConfigFile, es decir, cargar a partir de un archivo.

Recuerde la sintaxis de la sentencia grant es (todos son parámetros opcionales donde el orden no importa):

La sintaxis de <Principal field(s)> es:

Por si no lo sabe, los privilegios describen en base a esos Principals y estos son asociados al usuario (o servicio) que pretende realizar la operación, en el proceso de Autentificación.

Por ejemplo: Si eres un usuario (Subject) que tiene entre todos sus principals un GroupPricipal de nombre “administrador”, entonces puedes realizar esta operación, ver esta ventana, etc…

En nuestro ejemplo, estamos diciendo, si posees un SimplePrincipal de nombre “usuario2″, entonces tienes permisos para listar el directorio c:/

Es decir, el concepto de Principal y de Permission son conceptos abstractos que podemos implementar en base a nuestras necesidades… Los FrameWorks nos abstraen de esto definiendo ellos mismos estos conceptos.

Aplicación que será autentificada y autorizada mediante JAAS

A continuación, mostramos el código fuente de nuestra aplicación (en este caso de escritorio) que realizará la autentificación y la autorización de las operaciones sobre el usuario que se loge.

Vuelvo a repetir, los FrameWork de seguridad como Spring Security nos abstraen de todo esto, pero ellos lo realizan por dentro.

Acciones realizadas por la aplicación y autorizadas o no por el AccessController de Java Security

Las siguientes operaciones están vigiladas por al Access Controller

Implementación de un LoginModule que autentifica a los usuarios a través de su usuario y su contraseña

El módulo está autocomentario, debería ser suficiente para que comprenda los pasos a realiazar.

Implementación de javax.security.auth.callback.CallbackHandler: Solicitando al usuario su login y el contraseña.

A continuación, implementamos un CallBackHandler que pide el nombre de usuario y la contraseña al usuario.

Existen multitud de implementaciones disponibles, como por ejemplo, que nos muestre una ventana Swing GUI para pedir la información requerida en la autentificación.