# US-FUND-001: Autenticación básica con JWT **Épica:** EAI-001 - Fundamentos **Sprint:** Mes 1, Semana 1 **Story Points:** 8 SP **Presupuesto:** $2,900 MXN **Prioridad:** Alta (Alcance Inicial) **Estado:** ✅ Completada (Mes 1) --- ## Descripción Como **estudiante o profesor**, quiero poder **registrarme, iniciar sesión y recuperar mi contraseña** para **acceder de forma segura a la plataforma GAMILIT**. **Contexto del Alcance Inicial:** En el MVP se implementó un sistema de autenticación básico con JWT que soporta dos roles fijos: estudiante y profesor. El sistema incluye funcionalidades esenciales de autenticación sin características avanzadas como 2FA o SSO, que serán agregadas en extensiones futuras. --- ## Criterios de Aceptación - [ ] **CA-01:** El sistema permite registrar nuevos usuarios con email, contraseña y rol (estudiante/profesor) - [ ] **CA-02:** Al registrarse, se valida que el email sea único y tenga formato válido - [ ] **CA-03:** Las contraseñas se almacenan hasheadas con bcrypt (min. 10 rounds) - [ ] **CA-04:** El login genera un JWT token válido por 24 horas - [ ] **CA-05:** El JWT incluye el userId y rol en el payload - [ ] **CA-06:** Existe un endpoint de recuperación de contraseña que envía email con token temporal - [ ] **CA-07:** El token de recuperación expira en 1 hora - [ ] **CA-08:** El sistema permite cerrar sesión (invalidación de token en frontend) - [ ] **CA-09:** Las contraseñas deben tener mínimo 8 caracteres - [ ] **CA-10:** Se retorna mensaje de error apropiado para credenciales inválidas --- ## Especificaciones Técnicas ### Backend (NestJS) **Endpoints:** ``` POST /api/auth/register (public self-service) - Body: { email, password, first_name?, last_name? } - Response: { user, accessToken } - Note: role is assigned automatically as 'student' POST /api/auth/login - Body: { email, password } - Response: { user, accessToken } POST /api/auth/forgot-password - Body: { email } - Response: { message: "Email sent" } POST /api/auth/reset-password - Body: { token, newPassword } - Response: { message: "Password updated" } GET /api/auth/me - Headers: Authorization: Bearer {token} - Response: { user } ``` **Servicios:** - **AuthService:** Lógica de autenticación (register, login, validateUser) - **JwtService:** Generación y validación de tokens JWT - **MailService:** Envío de emails de recuperación **Entidades:** ```typescript @Entity('users') class User { id: string (UUID) email: string (unique) password: string (hashed) first_name: string // snake_case for DB consistency last_name: string // snake_case for DB consistency role: 'student' | 'teacher' createdAt: Date updatedAt: Date } @Entity('password_reset_tokens') class PasswordResetToken { id: string (UUID) userId: string (FK to users) token: string expiresAt: Date used: boolean } ``` **Guards:** - **JwtAuthGuard:** Protege rutas que requieren autenticación - **RolesGuard:** Valida roles específicos (estudiante/profesor) ### Frontend (React + Vite) **Componentes:** - `LoginForm.tsx`: Formulario de inicio de sesión - `RegisterForm.tsx`: Formulario de registro - `ForgotPasswordForm.tsx`: Solicitud de recuperación - `ResetPasswordForm.tsx`: Establecer nueva contraseña **Estado (Zustand):** ```typescript interface AuthStore { user: User | null token: string | null isAuthenticated: boolean login: (email, password) => Promise register: (data) => Promise logout: () => void forgotPassword: (email) => Promise resetPassword: (token, newPassword) => Promise } ``` **Rutas:** - `/login` - Página de inicio de sesión - `/register` - Página de registro - `/forgot-password` - Solicitar recuperación - `/reset-password/:token` - Restablecer contraseña **Almacenamiento:** - Token JWT guardado en `localStorage` - Auto-login si existe token válido al cargar la app ### Seguridad - Contraseñas hasheadas con bcrypt (10 rounds) - JWT firmado con secret key (desde ENV) - Tokens de recuperación de un solo uso - Validación de email en backend y frontend - Rate limiting en endpoints de auth (10 req/min) --- ## Dependencias **Antes:** - Ninguna (primera historia del proyecto) **Después:** - US-FUND-002 (Perfiles de usuario - requiere autenticación) - US-FUND-003 (Dashboard - requiere autenticación) - US-FUND-005 (Sistema de sesiones - extiende esta funcionalidad) --- ## Definición de Hecho (DoD) - [x] Código implementado y revisado - [x] Tests unitarios para AuthService (>80% coverage) - [x] Tests E2E para flujos de autenticación - [x] Validación de seguridad (password hashing, JWT signing) - [x] Documentación de API en Swagger - [x] Probado en ambiente de desarrollo - [x] Sin warnings de seguridad en audit --- ## Notas del Alcance Inicial - ✅ Solo 2 roles básicos: estudiante y profesor - ✅ JWT simple sin refresh tokens (agregado en US-FUND-005) - ✅ Recuperación de contraseña por email (requiere configuración SMTP) - ✅ Sin autenticación social (Google, Facebook) - ✅ Sin autenticación de dos factores (2FA) - ⚠️ **Extensión futura:** EXT-001-Admin (roles adicionales: admin, superadmin) - ⚠️ **Extensión futura:** EXT-002-Security (2FA, SSO, OAuth) --- ## Tareas de Implementación ### Backend (Estimado: 16h, Real: 17h) **Total Backend:** 17h (~4.25 SP) - [x] **Tarea B.1:** Configuración JWT y entidades base - Estimado: 4h, Real: 4.5h - [x] Subtarea B.1.1: Instalar dependencias (@nestjs/jwt, @nestjs/passport, bcrypt) - 0.5h - [x] Subtarea B.1.2: Crear entidad User con campos de autenticación - 1h - [x] Subtarea B.1.3: Crear entidad PasswordResetToken - 0.5h - [x] Subtarea B.1.4: Generar migración de base de datos - 0.5h - [x] Subtarea B.1.5: Configurar JwtModule con variables de entorno - 1h - [x] Subtarea B.1.6: Crear JwtStrategy para validación de tokens - 1h - [x] **Tarea B.2:** Implementación de AuthService - Estimado: 5h, Real: 5.5h - [x] Subtarea B.2.1: Método register con hash de contraseña (bcrypt 10 rounds) - 2h - [x] Subtarea B.2.2: Método login con validación de credenciales - 1.5h - [x] Subtarea B.2.3: Método validateUser para JWT strategy - 1h - [x] Subtarea B.2.4: Generación de tokens JWT con payload (userId, role) - 1h - [x] **Tarea B.3:** Endpoints de autenticación - Estimado: 4h, Real: 4h - [x] Subtarea B.3.1: POST /auth/register con validación de DTO - 1.5h - [x] Subtarea B.3.2: POST /auth/login con manejo de errores - 1h - [x] Subtarea B.3.3: GET /auth/me con JWT guard - 1h - [x] Subtarea B.3.4: Documentación Swagger de endpoints - 0.5h - [x] **Tarea B.4:** Sistema de recuperación de contraseña - Estimado: 3h, Real: 3h - [x] Subtarea B.4.1: MailService para envío de emails - 1h - [x] Subtarea B.4.2: POST /auth/forgot-password con generación de token - 1h - [x] Subtarea B.4.3: POST /auth/reset-password con validación de token - 1h ### Frontend (Estimado: 8h, Real: 9h) **Total Frontend:** 9h (~2.25 SP) - [x] **Tarea F.1:** Componentes de autenticación - Estimado: 5h, Real: 5.5h - [x] Subtarea F.1.1: Componente LoginForm con validación - 1.5h - [x] Subtarea F.1.2: Componente RegisterForm con validación - 1.5h - [x] Subtarea F.1.3: Componente ForgotPasswordForm - 1h - [x] Subtarea F.1.4: Componente ResetPasswordForm - 1h - [x] Subtarea F.1.5: Páginas de rutas (/login, /register, etc.) - 0.5h - [x] **Tarea F.2:** Estado de autenticación con Zustand - Estimado: 3h, Real: 3.5h - [x] Subtarea F.2.1: Crear AuthStore con interface - 1h - [x] Subtarea F.2.2: Implementar métodos login/register/logout - 1.5h - [x] Subtarea F.2.3: Persistencia de token en localStorage - 0.5h - [x] Subtarea F.2.4: Hook useAuth para acceso al store - 0.5h ### Testing (Estimado: 6h, Real: 5.5h) **Total Testing:** 5.5h (~1.4 SP) - [x] **Tarea T.1:** Tests unitarios backend - Estimado: 3h, Real: 2.5h - [x] Subtarea T.1.1: Tests de AuthService (hash, JWT, validación) - 1.5h - [x] Subtarea T.1.2: Tests de MailService - 0.5h - [x] Subtarea T.1.3: Tests de guards (JwtAuthGuard) - 0.5h - [x] **Tarea T.2:** Tests E2E - Estimado: 2h, Real: 2h - [x] Subtarea T.2.1: Tests de endpoints de auth (register, login) - 1h - [x] Subtarea T.2.2: Tests de recuperación de contraseña - 0.5h - [x] Subtarea T.2.3: Tests de protección de rutas (401) - 0.5h - [x] **Tarea T.3:** Tests frontend - Estimado: 1h, Real: 1h - [x] Subtarea T.3.1: Tests de componentes de formularios - 0.5h - [x] Subtarea T.3.2: Tests de AuthStore - 0.5h ### Deployment (Estimado: 2h, Real: 2h) **Total Deployment:** 2h (~0.5 SP) - [x] **Tarea D.1:** Configuración de ambiente - Estimado: 1h, Real: 1h - [x] Subtarea D.1.1: Variables de entorno JWT_SECRET - 0.25h - [x] Subtarea D.1.2: Configuración SMTP para emails - 0.5h - [x] Subtarea D.1.3: Secrets management en .env - 0.25h - [x] **Tarea D.2:** Deploy y validación - Estimado: 1h, Real: 1h - [x] Subtarea D.2.1: Deploy a staging - 0.5h - [x] Subtarea D.2.2: Smoke tests de autenticación - 0.25h - [x] Subtarea D.2.3: Validación de seguridad (bcrypt, JWT) - 0.25h --- ## Resumen de Horas | Categoría | Estimado | Real | Variación | |-----------|----------|------|-----------| | Backend | 16h | 17h | +6.25% | | Frontend | 8h | 9h | +12.5% | | Testing | 6h | 5.5h | -8.3% | | Deployment | 2h | 2h | 0% | | **TOTAL** | **32h** | **33.5h** | **+4.7%** | **Validación:** 8 SP × 4h/SP = 32 horas estimadas ✅ --- ## Cronograma Real **Sprint:** Sprint 1-2 (05-16 Agosto 2024) **Fecha Inicio Real:** 05 Agosto 2024 **Fecha Fin Real:** 08 Agosto 2024 **Estado:** ✅ Completada **Notas:** La implementación tomó 0.5 días adicionales debido a la configuración del servicio de email SMTP que requirió troubleshooting. El sistema de autenticación quedó robusto con todas las validaciones de seguridad implementadas. --- ## Testing ### Tests Unitarios ```typescript describe('AuthService', () => { it('should hash password on register') it('should generate JWT on successful login') it('should throw error for invalid credentials') it('should create password reset token') it('should validate reset token expiry') }) ``` ### Tests E2E ```typescript describe('Auth API', () => { it('POST /auth/register - success') it('POST /auth/register - duplicate email') it('POST /auth/login - success') it('POST /auth/login - invalid credentials') it('GET /auth/me - with valid token') it('GET /auth/me - without token (401)') }) ``` --- ## Estimación **Desglose de Esfuerzo (8 SP = ~3 días):** - Backend setup + JWT config: 1 día - Endpoints de auth: 1 día - Frontend forms + store: 0.5 días - Password reset flow: 0.5 días - Testing: 0.5 días - Ajustes y documentación: 0.5 días **Riesgos:** - Configuración de email service puede requerir tiempo adicional - Validaciones de seguridad requieren atención especial --- **Creado:** 2025-11-02 **Actualizado:** 2025-11-02 **Responsable:** Equipo Backend + Frontend