Autenticación segura en Kotlin: guía para desarrolladores

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

Introducción: ¿por qué la autenticación "hecha en casa" es un riesgo?

\n\n

Imagina: estás escribiendo una aplicación en Kotlin, ya sea un cliente Android o un backend con Ktor/Spring Boot. Rápidamente creas un formulario de inicio de sesión, guardas la contraseña en SharedPreferences y te alegras de que todo funciona. Y una semana después recibes un mensaje: "Su aplicación fue hackeada, los datos se filtraron". ¿Te suena? Lamentablemente, es un clásico.

\n\n

La autenticación segura en Kotlin no es solo "verificar la contraseña". Es todo un ecosistema: hash, tokens, protección contra falsificación de solicitudes, almacenamiento seguro de secretos. En este artículo, analizaremos cómo evitar errores típicos y construir un sistema de inicio de sesión robusto. ¡Allá vamos!

\n\n

1. Hash de contraseñas: bcrypt y sus amigos

\n\n

La primera regla de seguridad: nunca almacenes contraseñas en texto plano. Incluso si usas HTTPS, la base de datos puede verse comprometida. Tu tarea es almacenar solo el hash.

\n\n

¿Por qué MD5 y SHA son malos?

\n

Estos algoritmos son rápidos. Y los hashes rápidos son el sueño de un atacante: puede probar miles de millones de combinaciones por segundo. En su lugar, usa bcrypt, scrypt o Argon2. Son intencionalmente lentos y resistentes a ataques con GPU.

\n\n

Ejemplo en Kotlin usando la librería jbcrypt:

\n\n
import org.mindrot.jbcrypt.BCrypt\n\nfun hashPassword(password: String): String {\n    val salt = BCrypt.gensalt(12) // factor de costo 12 — óptimo\n    return BCrypt.hashpw(password, salt)\n}\n\nfun checkPassword(password: String, hashed: String): Boolean {\n    return BCrypt.checkpw(password, hashed)\n}
\n\n

Importante: la sal se genera automáticamente y se incrusta en el hash. No necesitas almacenarla por separado.

\n\n

2. JWT: autenticación ligera y segura

\n\n

JSON Web Token (JWT) es un estándar para transmitir afirmaciones (claims) entre partes. En Kotlin, puedes usar la librería java-jwt (Auth0) o jsonwebtoken (jjwt).

\n\n

Generación de JWT en Kotlin

\n\n
import io.jsonwebtoken.Jwts\nimport io.jsonwebtoken.SignatureAlgorithm\nimport io.jsonwebtoken.security.Keys\nimport java.util.Date\n\nfun generateToken(userId: String, secretKey: String): String {\n    val key = Keys.hmacShaKeyFor(secretKey.toByteArray())\n    return Jwts.builder()\n        .setSubject(userId)\n        .setIssuedAt(Date())\n        .setExpiration(Date(System.currentTimeMillis() + 3600_000)) // 1 hora\n        .signWith(key, SignatureAlgorithm.HS256)\n        .compact()\n}
\n\n

Validación del token

\n\n
fun validateToken(token: String, secretKey: String): String? {\n    return try {\n        val key = Keys.hmacShaKeyFor(secretKey.toByteArray())\n        val claims = Jwts.parserBuilder()\n            .setSigningKey(key)\n            .build()\n            .parseClaimsJws(token)\n            .body\n        claims.subject // devolvemos userId\n    } catch (e: Exception) {\n        null // token inválido o expirado\n    }\n}
\n\n

Consejo: no almacenes la clave secreta en el código. Usa variables de entorno o Vault.

\n\n

3. Almacenamiento seguro de tokens en Android

\n\n

Si estás escribiendo una aplicación móvil en Kotlin, el token de acceso no debe almacenarse en SharedPreferences: es un archivo abierto que otras aplicaciones o un atacante con acceso root pueden leer.

\n\n

Usa EncryptedSharedPreferences (de AndroidX Security) o Keystore:

\n\n
import androidx.security.crypto.EncryptedSharedPreferences\nimport androidx.security.crypto.MasterKey\n\nfun saveToken(context: Context, token: String) {\n    val masterKey = MasterKey.Builder(context)\n        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)\n        .build()\n\n    val sharedPreferences = EncryptedSharedPreferences.create(\n        context,\n        "secure_prefs",\n        masterKey,\n                

Blogs

Book Recommendations