Autorización y autenticación en Rust: desde JWT hasta sesiones
En el mundo de la programación de sistemas y web, Rust se ha ganado la reputación de ser un lenguaje seguro y rápido. Sin embargo, al crear aplicaciones web, los desarrolladores a menudo se enfrentan a la tarea de implementar 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 las bibliotecas y enfoques clave para implementar estos mecanismos en Rust, y proporcionaremos ejemplos prácticos de código.
Conceptos básicos de autenticación y autorización
Antes de pasar a las herramientas, es importante diferenciar los conceptos:
- Autenticación — el proceso de verificar que el usuario es quien dice ser. Generalmente se realiza mediante inicio de sesión/contraseña, tokens o biometría.
- Autorización — la determinación de qué recursos y acciones están disponibles para un usuario autenticado. A menudo se implementa a través de roles (administrador, moderador, usuario) o permisos de acceso.
En Rust, ambos procesos se pueden implementar tanto a bajo nivel (gestión manual de tokens) como con la ayuda de bibliotecas listas para usar.
Bibliotecas populares para autenticación en Rust
Para trabajar con sesiones y tokens en Rust, existen varias soluciones maduras:
actix-identity— para la gestión de sesiones en el framework web Actix-web. Soporta sesiones basadas en cookies y Redis.jsonwebtoken— biblioteca para trabajar con JWT (JSON Web Tokens). Permite crear, firmar y verificar tokens.argon2— implementación del algoritmo de hash de contraseñas Argon2, recomendado por OWASP.bcrypt— biblioteca clásica para el hash de contraseñas.
A continuación, veremos cada herramienta con un ejemplo.
Ejemplo 1: Autenticación con JWT y jsonwebtoken
JWT es una de las formas más populares de autenticación en API REST. El token contiene afirmaciones (claims) y está firmado con una clave secreta. Veamos una implementación básica usando la biblioteca jsonwebtoken.
// cargo add jsonwebtoken serdeuse jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]struct Claims { sub: String, // identificador de usuario exp: usize, // tiempo de expiración (timestamp UNIX) role: String, // rol del usuario}
fn create_token(user_id: &str, role: &str) -> Result<String, jsonwebtoken::errors::Error> { let claims = Claims { sub: user_id.to_owned(), exp: (chrono::Utc::now() + chrono::Duration::hours(24)).timestamp() as usize, role: role.to_owned(), }; encode( &Header::default(), &claims, &EncodingKey::from_secret(b"su_clave_secreta") )}
fn verify_token(token: &str) -> Result<Claims, jsonwebtoken::errors::Error> { let token_data = decode::<Claims>( token, &DecodingKey::from_secret(b"su_clave_secreta"), &Validation::default() )?; Ok(token_data.claims)}En este ejemplo, creamos un token con una validez de 24 horas que contiene el ID del usuario y su rol. La función verify_token verifica la firma y devuelve los claims, que se pueden usar para la autorización.
Ejemplo 2: Hash de contraseñas con Argon2
¡Nunca almacene contraseñas en texto plano! Use Argon2, un algoritmo de hash moderno y seguro.
// cargo add argon2use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier};use argon2::password_hash::{SaltString, rand_core::OsRng};
fn hash_password(password: &str) -> String { let salt = SaltString::generate(&mut OsRng); let argon2 = Argon2::default(); argon2.hash_password(password.as_bytes(), &salt) .expect("Error al generar el hash") También en la biblioteca
Internacionalización (i18n) en Node.js: i18next y polyglot
Trabajo con Excel en Rust: bibliotecas para lectura y escritura
Migraciones de bases de datos en Java: descripción general de herramientas populares