Tokens JWT en Kotlin: generación, verificación y uso con io.jsonwebtoken

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

Tokens JWT en Kotlin: guía completa con la biblioteca jjwt

\n\n

En el desarrollo web moderno, los JWT (JSON Web Tokens) se han convertido en el estándar para la autenticación y el intercambio de información entre el cliente y el servidor. En el ecosistema de Kotlin, especialmente al crear aplicaciones backend con Spring Boot o Ktor, surge a menudo la necesidad de trabajar con JWT. En este artículo, analizaremos la biblioteca io.jsonwebtoken (jjwt), la herramienta más popular para trabajar con JWT en Java/Kotlin.

\n\n

¿Qué es JWT?

\n

JWT es una forma compacta y segura para URL de representar afirmaciones (claims) entre dos partes. El token consta de tres partes separadas por puntos:

\n
    \n
  • Header — encabezado que contiene el tipo de token y el algoritmo de firma (por ejemplo, HS256, RS256).
  • \n
  • Payload — carga útil con las afirmaciones (claims): sub (sujeto), iat (fecha de emisión), exp (fecha de vencimiento) y datos personalizados.
  • \n
  • Signature — firma creada con una clave secreta o un par de claves.
  • \n
\n\n

Inclusión de la biblioteca

\n

Para trabajar con JWT en Kotlin usaremos jjwt (io.jsonwebtoken). Agregue la dependencia en build.gradle.kts:

\n
dependencies {\n    implementation("io.jsonwebtoken:jjwt-api:0.12.6")\n    runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.6")\n    runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.6") // para análisis JSON\n}
\n\n

Generación de un token JWT

\n

Para crear un token, es necesario definir una clave secreta, establecer las afirmaciones y firmar el token. Ejemplo en Kotlin:

\n
import io.jsonwebtoken.Jwts\nimport io.jsonwebtoken.security.Keys\nimport java.util.Date\nimport javax.crypto.SecretKey\n\nfun generateToken(userId: String, secret: String): String {\n    val key: SecretKey = Keys.hmacShaKeyFor(secret.toByteArray())\n    \n    val now = Date()\n    val expiration = Date(now.time + 3600_000) // +1 hora\n    \n    return Jwts.builder()\n        .subject(userId)\n        .issuedAt(now)\n        .expiration(expiration)\n        .claim("role", "USER")\n        .signWith(key)\n        .compact()\n}
\n\n

Verificación y análisis de JWT

\n

Al recibir un token del cliente, es necesario verificar su firma y fecha de vencimiento. Use Jwts.parser():

\n
import io.jsonwebtoken.JwtException\nimport io.jsonwebtoken.Jwts\nimport io.jsonwebtoken.security.Keys\nimport javax.crypto.SecretKey\n\nfun validateToken(token: String, secret: String): Boolean {\n    return try {\n        val key: SecretKey = Keys.hmacShaKeyFor(secret.toByteArray())\n        Jwts.parser()\n            .verifyWith(key)\n            .build()\n            .parseSignedClaims(token)\n        true\n    } catch (e: JwtException) {\n        false\n    }\n}\n\nfun extractUserId(token: String, secret: String): String? {\n    return try {\n        val key: SecretKey = Keys.hmacShaKeyFor(secret.toByteArray())\n        val claims = Jwts.parser()\n            .verifyWith(key)\n            .build()\n            .parseSignedClaims(token)\n            .payload\n        claims.subject\n    } catch (e: Exception) {\n        null\n    }\n}
\n\n

Trabajo con claims personalizados

\n

Puede agregar cualquier dato arbitrario al payload. Por ejemplo, almacenar el email o el rol del usuario:

\n
fun generateTokenWithCustomClaims(userId: String, email: String, secret: String): String {\n    val key = Keys.hmacShaKeyFor(secret.toByteArray())\n    \n    return Jwts.builder()\n        .subject(userId)\n        .claim("email", email)\n        .claim("isAdmin", false)\n        .issuedAt(Date())\n        .expiration(Date(System.currentTimeMillis() + 3600_000))\n        .signWith(key)\n        .compact()\n}\n\nfun extractCustomClaim(token: String, secret: String): String? {\n    val key = Keys.hmacShaKeyFor(secret.toByteArray())\n                    

Recommendations