Implementación de Autenticación con JSON Web Tokens en Spring Boot

Clase 18 de 23Curso de Java Spring Security: Autenticación y Seguridad Web

Contenido del curso

Configuración de seguridad

Resumen

Cuando un usuario necesita autenticarse en una API protegida con Spring Security, el flujo más común consiste en recibir credenciales, validarlas contra la base de datos y devolver un JSON Web Token que el cliente adjuntará en cada petición futura. Aquí se detalla paso a paso cómo construir ese controlador de login, inyectar el Authentication Manager y responder con el token en el encabezado authorization.

¿Cómo funciona el flujo de autenticación con JWT?

El proceso parte de un authentication request que llega al AuthController en su método login [00:18]. Desde ahí se invoca al Authentication Manager, quien delega en el DAO Authentication Provider. Este provider consulta al UserSecurityService —la implementación de UserDetailService— para recuperar al usuario desde MySQL [00:42].

Una vez obtenido el usuario, el Authentication Provider compara la contraseña recibida con la almacenada en base de datos:

  • Si no coinciden, se responde con un HTTP 401 (unauthorized).
  • Si coinciden, se genera un status 200 y se devuelve el JWT en el encabezado Authorization [01:02].

¿Cómo crear el AuthController y el LoginDTO?

El controlador se anota con @RestController y @RequestMapping("/api/auth") [01:20]. Su método login atiende peticiones POST en /login y recibe un objeto LoginDTO anotado con @RequestBody.

¿Qué contiene el LoginDTO?

Es una clase sencilla dentro de la capa service/dto, anotada con @Data, que expone dos atributos [01:42]:

  • username: nombre del usuario.
  • password: contraseña en texto plano.

¿Cómo se registra el Authentication Manager como bean?

Dentro de SecurityConfig se crea un método público que retorna un AuthenticationManager a partir del AuthenticationConfiguration [02:10]:

java @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception { return configuration.getAuthenticationManager(); }

La anotación @Bean es imprescindible para que Spring lo registre en su ciclo de vida y permita la inyección de dependencias en el controlador [02:48].

¿Cómo se autentica al usuario y se genera el token?

Dentro del método login se construye un UsernamePasswordAuthenticationToken con las credenciales del DTO [03:08]:

java UsernamePasswordAuthenticationToken login = new UsernamePasswordAuthenticationToken(loginDTO.getUsername(), loginDTO.getPassword());

Authentication authentication = this.authenticationManager.authenticate(login);

Si la ejecución supera la línea del authenticate, el usuario ya está autenticado [03:30]. Se puede verificar con authentication.isAuthenticated() y consultar el principal que contiene los datos del usuario en el contexto de seguridad de Spring.

A continuación se genera el JWT inyectando JwtTokenUtil y llamando a su método create [04:00]:

java String jwt = jwtTokenUtil.create(loginDTO.getUsername());

return ResponseEntity.ok() .header(HttpHeaders.AUTHORIZATION, jwt) .build();

El cuerpo de la respuesta queda vacío; el token viaja exclusivamente en el encabezado Authorization.

¿Por qué hay que permitir el endpoint de login sin autenticación?

Sin esta configuración, Spring Security bloquea la petición antes de llegar al controlador y responde 401 [05:22]. En SecurityConfig, la primera regla tras authorizeHttpRequests debe ser:

java .requestMatchers("/api/auth/**").permitAll()

Esto garantiza que cualquier usuario pueda acceder al endpoint de login sin necesidad de un token previo [05:35].

¿Cómo se verifica el resultado en Postman?

Se envía una petición POST a /api/auth/login con el siguiente cuerpo JSON [05:05]:

{ "username": "admin", "password": "admin123" }

  • Con credenciales válidas se obtiene un 200 y el encabezado Authorization contiene el JWT generado [05:55].
  • Con credenciales inválidas se recibe un 401 sin encabezado de autorización [06:10].

En la consola de IntelliJ se imprime true —confirmando la autenticación— junto con el principal que muestra el usuario admin, su rol y permisos [06:25]. Incluso se puede añadir un toString al UserEntity para rastrear los atributos exactos que pasan por el UserSecurityService durante el flujo [06:50].

Con este servicio listo, el siguiente paso será crear dentro de JwtTokenUtil un método que valide si un JSON Web Token es legítimo antes de permitir el acceso a recursos protegidos. ¿Ya has probado este flujo en tu proyecto? Comparte tu experiencia en los comentarios.