diff --git a/src/domain/services/auth_service.rs b/src/domain/services/auth_service.rs deleted file mode 100644 index dbb11cb6..00000000 --- a/src/domain/services/auth_service.rs +++ /dev/null @@ -1,204 +0,0 @@ -use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey, Algorithm}; -use serde::{Serialize, Deserialize}; -use uuid::Uuid; -use chrono::Utc; - -use crate::domain::entities::user::User; -use crate::common::errors::{DomainError, ErrorKind}; - -/** - * JWT claims structure for authentication tokens. - * - * This structure represents the payload of JWT tokens used for authentication - * in the system. It contains all the necessary claims to identify users and - * manage token lifecycle. - */ -#[derive(Debug, Serialize, Deserialize)] -pub struct TokenClaims { - /// Subject identifier - contains the user ID - pub sub: String, - - /// Expiration timestamp (seconds since Unix epoch) - pub exp: i64, - - /// Issued at timestamp (seconds since Unix epoch) - pub iat: i64, - - /// JWT unique ID for token tracking and revocation - pub jti: String, - - /// Username for display and identification purposes - pub username: String, - - /// User email for communication and identification - pub email: String, - - /// User role for authorization checks - pub role: String, -} - -/** - * Authentication-specific error types. - * - * This enum encapsulates all error scenarios that can occur during - * authentication and authorization processes, providing clear error messages - * and categorization for proper handling. - */ -#[derive(Debug, thiserror::Error)] -pub enum AuthError { - /// Returned when username/password authentication fails - #[error("Credenciales inválidas")] - InvalidCredentials, - - /// Returned when a JWT token has passed its expiration time - #[error("Token expirado")] - TokenExpired, - - /// Returned when a JWT token is malformed or has invalid signature - #[error("Token inválido: {0}")] - InvalidToken(String), - - /// Returned when a user attempts to access a resource they don't have permission for - #[error("Acceso denegado: {0}")] - AccessDenied(String), - - /// Returned when a requested operation is not allowed for the user - #[error("Operación no permitida: {0}")] - OperationNotAllowed(String), - - /// Returned for unexpected errors in the authentication system - #[error("Error interno: {0}")] - InternalError(String), -} - -/** - * Conversion from AuthError to DomainError. - * - * This implementation allows authentication errors to be seamlessly - * transformed into domain errors, making error handling more consistent - * throughout the application. - */ -impl From for DomainError { - fn from(err: AuthError) -> Self { - match err { - AuthError::InvalidCredentials => { - DomainError::new(ErrorKind::AccessDenied, "Auth", "Credenciales inválidas") - }, - AuthError::TokenExpired => { - DomainError::new(ErrorKind::AccessDenied, "Auth", "Token expirado") - }, - AuthError::InvalidToken(msg) => { - DomainError::new(ErrorKind::AccessDenied, "Auth", format!("Token inválido: {}", msg)) - }, - AuthError::AccessDenied(msg) => { - DomainError::new(ErrorKind::AccessDenied, "Auth", msg) - }, - AuthError::OperationNotAllowed(msg) => { - DomainError::new(ErrorKind::AccessDenied, "Auth", msg) - }, - AuthError::InternalError(msg) => { - DomainError::new(ErrorKind::InternalError, "Auth", msg) - }, - } - } -} - -/** - * Authentication service for managing user sessions and authorization. - * - * This service provides the core authentication functionality for the system, - * including JWT token generation and validation, refresh token management, - * and session duration control. - */ -pub struct AuthService { - /// Secret key used for signing JWT tokens - jwt_secret: String, - - /// Expiration time for access tokens in seconds - access_token_expiry: i64, - - /// Expiration time for refresh tokens in seconds - refresh_token_expiry: i64, -} - -impl AuthService { - pub fn new(jwt_secret: String, access_token_expiry_secs: i64, refresh_token_expiry_secs: i64) -> Self { - Self { - jwt_secret, - access_token_expiry: access_token_expiry_secs, - refresh_token_expiry: refresh_token_expiry_secs, - } - } - - pub fn generate_access_token(&self, user: &User) -> Result { - let now = Utc::now().timestamp(); - - // Log information for debugging - tracing::debug!( - "Generating token for user: {}, id: {}, role: {}", - user.username(), - user.id(), - user.role() - ); - - let claims = TokenClaims { - sub: user.id().to_string(), - exp: now + self.access_token_expiry, - iat: now, - jti: Uuid::new_v4().to_string(), - username: user.username().to_string(), - email: user.email().to_string(), - role: format!("{}", user.role()), - }; - - // Log JWT claims for debugging - tracing::debug!("JWT claims: sub={}, exp={}, iat={}", claims.sub, claims.exp, claims.iat); - - match encode( - &Header::default(), - &claims, - &EncodingKey::from_secret(self.jwt_secret.as_bytes()) - ) { - Ok(token) => { - tracing::debug!("Token generated successfully, length: {}", token.len()); - Ok(token) - }, - Err(e) => { - tracing::error!("Error generating token: {}", e); - Err(AuthError::InternalError(format!("Error al generar token: {}", e))) - } - } - } - - pub fn generate_refresh_token(&self) -> String { - Uuid::new_v4().to_string() - } - - pub fn validate_token(&self, token: &str) -> Result { - let validation = Validation::new(Algorithm::HS256); - - let token_data = decode::( - token, - &DecodingKey::from_secret(self.jwt_secret.as_bytes()), - &validation - ) - .map_err(|e| { - match e.kind() { - jsonwebtoken::errors::ErrorKind::ExpiredSignature => AuthError::TokenExpired, - _ => AuthError::InvalidToken(format!("Error al validar token: {}", e)), - } - })?; - - Ok(token_data.claims) - } - - // Duración del refresh token en segundos - pub fn refresh_token_expiry_secs(&self) -> i64 { - self.refresh_token_expiry - } - - // Duración del refresh token en días (para la entidad Session) - pub fn refresh_token_expiry_days(&self) -> i64 { - self.refresh_token_expiry / (24 * 3600) - } -} \ No newline at end of file