Introducción a OAuth 2.0 y JWT en Rust
Las aplicaciones web modernas requieren una autenticación robusta y segura. Dos estándares clave en este ámbito son OAuth 2.0 (protocolo de autorización) y JWT (JSON Web Token, formato de token de acceso). Rust, gracias a su rendimiento y seguridad de memoria, se convierte en una excelente opción para construir APIs donde la velocidad y la fiabilidad son críticas.
En este artículo, analizaremos cómo implementar la autorización OAuth 2.0 y JWT en Rust utilizando crates populares. Aprenderá a configurar un servidor, emitir y verificar tokens JWT, así como integrar el flujo OAuth 2.0. El material está dirigido a desarrolladores familiarizados con los fundamentos de Rust y los frameworks web.
Conceptos principales de OAuth 2.0 y JWT
¿Qué es OAuth 2.0?
OAuth 2.0 es un protocolo de acceso delegado. Permite que una aplicación obtenga acceso limitado a los recursos de un usuario sin transferir sus credenciales (nombre de usuario y contraseña). Los participantes principales son:
- Resource Owner — el usuario propietario de los datos.
- Client — nuestra aplicación (por ejemplo, un servicio web en Rust).
- Authorization Server — el servidor que emite tokens tras una autenticación exitosa.
- Resource Server — la API que proporciona los datos protegidos.
¿Qué es JWT?
JWT es un formato de token compacto y seguro para URL, compuesto por tres partes: encabezado (header), carga útil (payload) y firma (signature). La firma garantiza la integridad de los datos. JWT se utiliza a menudo como token de acceso (access token) en OAuth 2.0, ya que es autosuficiente: el servidor puede verificarlo sin necesidad de consultar una base de datos.
Implementación práctica en Rust
Para la implementación necesitaremos los siguientes crates:
actix-web— framework web.serdeyserde_json— para serialización/deserialización.jsonwebtoken— para trabajar con JWT.dotenv— para la gestión de configuración.chrono— para trabajar con fechas y horas.
Paso 1: Configuración del proyecto y estructura
Cree un nuevo proyecto Cargo y añada las dependencias en Cargo.toml:
[dependencies]actix-web = "4"actix-rt = "2"serde = { version = "1", features = ["derive"] }serde_json = "1"jsonwebtoken = "9"dotenv = "0.15"chrono = { version = "0.4", features = ["serde"] }uuid = { version = "1", features = ["v4"] }Cree un archivo .env para almacenar la clave secreta:
JWT_SECRET=my_super_secret_key_12345Paso 2: Creación del modelo de datos y funciones JWT
Definamos las estructuras para JWT e implementemos las funciones de creación y verificación de tokens.
use chrono::{Utc, Duration};use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};use serde::{Deserialize, Serialize};use std::env;
#[derive(Debug, Serialize, Deserialize)]pub struct Claims { pub sub: String, // identificador de usuario pub exp: usize, // tiempo de expiración (timestamp) pub iat: usize, // tiempo de emisión (timestamp)}
pub fn create_jwt(user_id: &str) -> Result<String, jsonwebtoken::errors::Error> { let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set"); let now = Utc::now(); let expiration = now + Duration::hours(24); // el token vive 24 horas
let claims = Claims { sub: user_id.to_owned(), exp: expiration.timestamp() as usize, iat: now.timestamp() as usize, };
let token = encode( &Header::default(), &claims, &EncodingKey::from_secret(secret.as_bytes()), )?; Ok(token)}
pub fn validate_jwt(token: &str) -> Result<Claims, jsonwebtoken
```