OAuth 2.0 y autorización JWT en Rust: guía paso a paso

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é OAuth 2.0 y JWT en Rust?

\n\n

Las aplicaciones web modernas rara vez prescinden de un sistema de autenticación y autorización. OAuth 2.0 es el estándar de la industria para la delegación de acceso, y JWT (JSON Web Tokens) es una forma compacta y segura de transferir afirmaciones entre partes. Rust, gracias a su rendimiento y seguridad de memoria, se está volviendo cada vez más popular para crear servidores de alta carga. En este artículo, analizaremos en la práctica cómo implementar la autorización OAuth 2.0 con JWT en Rust, utilizando crates populares y enfoques modernos.

\n\n

1. Preparación del proyecto e instalación de dependencias

\n\n

Para empezar, crearemos un nuevo proyecto en Rust y agregaremos las dependencias necesarias. Usaremos actix-web para el servidor web, jsonwebtoken para trabajar con JWT, serde para la serialización y reqwest para solicitudes HTTP a proveedores OAuth externos.

\n\n
# Cargo.toml\n[package]\nname = "oauth-jwt-rust"\nversion = "0.1.0"\nedition = "2021"\n\n[dependencies]\nactix-web = "4"\nactix-rt = "2"\njsonwebtoken = "9"\nserde = { version = "1.0", features = ["derive"] }\nserde_json = "1.0"\nreqwest = { version = "0.12", features = ["json"] }\ntokio = { version = "1", features = ["full"] }\ndotenv = "0.15"\nchrono = { version = "0.4", features = ["serde"] }\nuuid = { version = "1", features = ["v4"] }
\n\n

Crearemos un archivo .env para almacenar las claves secretas:

\n\n
JWT_SECRET=your_super_secret_key_here\nGITHUB_CLIENT_ID=your_github_client_id\nGITHUB_CLIENT_SECRET=your_github_client_secret
\n\n

2. Estructura básica de los tokens JWT

\n\n

JWT consta de tres partes: encabezado, carga útil y firma. Definiremos las estructuras para trabajar con tokens.

\n\n
// src/jwt.rs\nuse chrono::{Utc, Duration};\nuse jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};\nuse serde::{Deserialize, Serialize};\n\n#[derive(Debug, Serialize, Deserialize)]\npub struct Claims {\n    pub sub: String,       // identificador de usuario\n    pub email: String,     // email del usuario\n    pub exp: usize,        // tiempo de expiración\n    pub iat: usize,        // tiempo de emisión\n}\n\npub fn create_jwt(user_id: &str, email: &str) -> Result {\n    let now = Utc::now();\n    let expiration = now + Duration::hours(24); // el token vive 24 horas\n\n    let claims = Claims {\n        sub: user_id.to_string(),\n        email: email.to_string(),\n        exp: expiration.timestamp() as usize,\n        iat: now.timestamp() as usize,\n    };\n\n    let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set");\n    encode(\n        &Header::default(),\n        &claims,\n        &EncodingKey::from_secret(secret.as_bytes()),\n    )\n}\n\npub fn validate_jwt(token: &str) -> Result {\n    let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set");\n    let token_data = decode::(\n        token,\n        &DecodingKey::from_secret(secret.as_bytes()),\n        &Validation::default(),\n    )?;\n    Ok(token_data.claims)\n}
\n\n

3. Implementación de OAuth 2.0 con GitHub

\n\n

Consideremos el escenario clásico de OAuth 2.0: la autorización a través de GitHub. El usuario es redirigido a GitHub, después de la confirmación recibe un código que intercambiamos por un access token.

\n\n

3.1. Endpoint para iniciar el flujo OAuth

\n\n
// src/oauth.rs\nuse actix_web::{web, HttpResponse, HttpRequest};\nuse reqwest::Client;\nuse serde_json::Value;\n\npub async fn github_login() -> HttpResponse {\n    let client_id = std::env::var("GITHUB_CLIENT_ID").unwrap();\n    let redirect_uri = "http://localhost:8080/auth/github/callback";\n    \n    let auth_url = format!(\n        "https://github.com/login/oauth/authorize?client_id={}&redirect_uri={}&scope=user:email",\n        client_id, redirect_uri\n    );\n    \n    HttpRes                

Blogs

Book Recommendations