Saltar al contenido

Etiqueta: spring-security

JWT en Spring Boot y Spring Security

Hace poco tiempo participe en una hackaton con unos amigos, y cuando empezamos a desarrollar ya la aplicación luego de haber analizado lo que se buscaba solucionar, yo me valí de una plantilla en spring que había estado trabajando en mi tiempo libre, era la primera ves que la ponía a prueba en un escenario real y el sentido era que ahorraramos tiempo en configurar cosas que siempre son necesarias en todos los aplicativos. Para resumir un poco esta parte, la plantilla se porto como debía. Esta experiencia me lleva a realizar este post, en el que voy a explicar como se configura spring security y la autenticación en base de datos, además de que configurar para poder usarlo con una aplicación SPA del lado del frontend, como puede ser Angular, React, Vue.js entre otras.

Como deben de saber spring security es la librería de spring que nos brinda una visión dogmática de como se debería de implementar la seguridad en una aplicativo. Esto, claro siguiente todo un marco de buenas prácticas que muy probablemente si quisiéramos implementarla de 0, tranquilamente puede ser un proyecto entero sólo para esto. Gracias a esto, es que nos permite ahorrarnos mucho tiempo y nos brinda la seguridad de que estamos siguiendo un marco de buenas prácticas. Para nuestro caso, usaremos json web token (jwt) el cual es una de las alternativas que tenemos para implementar la autenticación.

Nuestra aplicación demo consta de distintas capas, ampliamente explicadas en post anteriores, tenemos un archivo de configuración “application.yml”, en la sección “security” hemos definido cierta información importante, entre las cuales está:

  • La url del enpoint de autenticación.
  • El tiempo máximo de expiración de un token.
  • La llave secreta que se usará para poder generar el JWT.

Se ha definido un paquete de configuración, y dentro de este un paquete de jwt, en el cual se tienen distintas clases necesarias para configurar, como es obvio en el pom del archivo se están añadiendo las dependencias de spring security.

Dependencia en el POM
Clases de configuración

Tenemos un controlador llamada “SecurityController”, en el cual tenemos los diferentes endpoint:

  • Authenticate [POST]: Nos permite iniciar sesión en el sistema, retorna el token.
  • Refresh [GET]: Permite refrescar el token que se ha generado, antes de que expire.
  • Create [POST]: Permite crear un usuario.

Tenemos en la capa service de nuestro aplicativo un “SecurityService” que es donde se realiza la lógica necesaria para autenticarse, refrescar el token y el crear un nuevo usuario, Por otro lado, en el repository, respetando el principio de single responsability tenemos tres clases (Person, Session y User) para el acceso a la base de datos.

El esquema de base de datos que vamos a usar es el siguiente:

Modelo E-R usado

Vamos a usar una clase a modo de helper, donde tendremos varios métodos utilitarios que nos van a permitir obtener información del token que generemos e incluso generarlo. Esta clase se llamará “JwtUtil”.

Métodos en JwtUtil

Luego es necesario crear una clase que extienda de “OncePerRequestFilter”, en el cual podamos hacer un override al método “doFilterInternal”, en le cual haremos un filtro a las peticiones que recibamos para determinar si poseen token o no y que acciones se deberían tomar. Esta clase la llamaremos “JwtTokenAuthorizationOncePerRequestFilter” y luego veremos donde debemos configurarla para que este filtro se lleve a cabo.

Clase JwtTokenAuthorizationOncePerRequestFilter

También es necesario crear un clase que extienda de “AuthenticationEntryPoint” para poder hacer un override del método “commence”, el cual será llamado cuando se determine que ser esta intentando acceder a un endpoint que requiere que se le pase un header de authorization. Esta clase, llevará el nombre de “JwtUnAuthorizedResponseAuthenticationEntryPoint”.

Clase JwtUnAuthorizedResponseAuthenticationEntryPoint

Finalmente, toda la magia ocurre en nuestra clase SecurityConfiguration, la cual extiende de “WebSecurityConfigurerAdapter”, en esta realizamos múltiples configuraciones que son propias de spring security, Entraremos al detalle de algunas en el post, pero en el video me daré más tiempo para explicar la configuración de esta clase. Uno de los override es al método “configure”, considerando que este método en la clase de la que estamos extiendo tiene varios overloads, el que explicaré en el post es el que posee como parametro de entrada un “HttpSecurity”, en debemos realizar las siguientes configuraciones:

  • Deshabilitar el CSRF
  • Indicar que authentication entrypoint (acá usamos nuestra entrypoint personalizado).
  • Indicamos que no usaremos sesiones, esto cambiando la configuración de “sessionCreationPolicy”.
  • Configuramos el CORS, para que permita todos los tipos de peticiones (GET, POST, DELETE, UPDATE, etc).
  • Añadimos el filtro que personalizamos anteriormente, esto con el “addFilterBefore”.
Clase SecurityConfiguration

Finalmente, revisemos nuestro “SecurityController”:

SecurityController

Realizemos algunas pruebas en postman de los distintos métodos.

  • Usuario: wgutierrez
  • Contraseña: $2a$10$3zHzb.Npv1hfZbLEU5qsdOju/tk2je6W6PnNnY.c1ujWPcZh4PL6e

Petición:

Solicitud al Authenticate endpoint

Respuesta:

Respuesta el Authenticate endpoint

Como se puede ver, se nos ha generado un token, si vamos a una página como jwt.io y ponemos el token que ha sido generado, tenemos la siguiente información:

Información del token generado

Los métodos de refresh y creación, pueden verlos a más detalle en el video que como de costumbre cuelgo con los post. Espero que les haya sido de ayuda, si tienen alguna duda les dejo el correspondiente repositorio en github, y los medios de contacto correspondientes.

REPO: GITHUB

Saludos.

Deja un comentario