Autorización y autenticación en Kotlin: JWT, Spring Security y Ktor

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Autorización y autenticación en Kotlin: guía completa

En el desarrollo web moderno con Kotlin, la seguridad de la aplicación comienza con la implementación correcta de la autenticación (verificación de la identidad del usuario) y la autorización (verificación de los permisos de acceso). En este artículo, exploraremos los enfoques principales, bibliotecas y herramientas para implementar estos mecanismos en las plataformas Spring Boot y Ktor.



Conceptos básicos

Antes de pasar al código, aclaremos los términos:

  • Autenticación — proceso de verificar que el usuario es quien dice ser (generalmente mediante usuario/contraseña, token o biometría).
  • Autorización — determinación de los permisos de acceso de un usuario autenticado (por ejemplo, acceso a rutas o datos específicos).
  • JWT (JSON Web Token) — token compacto y autónomo para transferir datos entre partes.
  • BCrypt — algoritmo de hash de contraseñas con sal, resistente a ataques de fuerza bruta.


Autenticación con JWT en Spring Boot

Spring Security proporciona una infraestructura potente para la autenticación. Veamos la implementación de autenticación JWT usando la biblioteca io.jsonwebtoken:jjwt.



// build.gradle.ktsdependencies {    implementation("org.springframework.boot:spring-boot-starter-security")    implementation("io.jsonwebtoken:jjwt-api:0.12.3")    runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.3")    runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.3")}


Creemos una clase utilitaria para trabajar con JWT:



import io.jsonwebtoken.*import io.jsonwebtoken.security.Keysimport org.springframework.stereotype.Componentimport java.security.Keyimport java.util.*

@Componentclass JwtUtil { private val secretKey: Key = Keys.secretKeyFor(SignatureAlgorithm.HS256) private val expirationMs: Long = 3600000 // 1 hora

fun generateToken(username: String): String { return Jwts.builder() .subject(username) .issuedAt(Date()) .expiration(Date(System.currentTimeMillis() + expirationMs)) .signWith(secretKey) .compact() }

fun extractUsername(token: String): String? { return try { Jwts.parser().verifyWith(secretKey).build() .parseSignedClaims(token).payload.subject } catch (e: Exception) { null } }

fun validateToken(token: String): Boolean { return try { Jwts.parser().verifyWith(secretKey).build() .parseSignedClaims(token) true } catch (e: JwtException) { false } }}


Filtro de autenticación para Spring Security

Ahora creemos un filtro que intercepte las solicitudes y verifique el token JWT:



import jakarta.servlet.FilterChainimport jakarta.servlet.http.HttpServletRequestimport jakarta.servlet.http.HttpServletResponseimport org.springframework.security.authentication.UsernamePasswordAuthenticationTokenimport org.springframework.security.core.context.SecurityContextHolderimport org.springframework.security.web.authentication.WebAuthenticationDetailsSourceimport org.springframework.stereotype.Componentimport org.springframework.web.filter.OncePerRequestFilter

@Componentclass JwtAuthFilter( private val jwtUtil: JwtUtil, private val userDetailsService: org.springframework.security.core.userdetails.UserDetailsService) : OncePerRequestFilter() {

override fun doFilterInternal( request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain ) { val authHeader = request.getHeader("Authorization") if (authHeader == null || !authHeader.startsWith("Bearer ")) { chain.doFilter(request, re

Recommendations