---
id: "US-AUTH-002"
title: "Login con Email"
type: "User Story"
status: "To Do"
priority: "Alta"
epic: "OQI-001"
story_points: 3
created_date: "2025-12-05"
updated_date: "2026-01-04"
---

# US-AUTH-002: Login con Email

**Version:** 1.0.0
**Fecha:** 2025-12-05
**Estado:** Pendiente
**Story Points:** 3
**Prioridad:** P0 (Crítica)
**Épica:** [OQI-001](../_MAP.md)

---

## Historia de Usuario

**Como** usuario registrado de Trading Platform
**Quiero** iniciar sesión con mi email y contraseña
**Para** acceder a mi cuenta y utilizar la plataforma

---

## Criterios de Aceptación

### AC-001: Formulario de login

**Dado** que soy un usuario registrado
**Cuando** accedo a la página de login
**Entonces** debería ver un formulario con:
- Campo de email
- Campo de contraseña
- Checkbox "Recordarme"
- Botón "Iniciar sesión"
- Link "¿Olvidaste tu contraseña?"
- Opciones de OAuth

### AC-002: Validación de campos

**Dado** que estoy en el formulario de login
**Cuando** intento enviar el formulario con campos vacíos
**Entonces** debería ver mensajes de error:
- "El email es requerido"
- "La contraseña es requerida"

### AC-003: Login exitoso

**Dado** que ingresé credenciales válidas
**Cuando** hago click en "Iniciar sesión"
**Entonces** debería:
1. Recibir un JWT token
2. Ser redirigido al dashboard
3. Ver mi nombre en el header
4. Tener la sesión activa

### AC-004: Credenciales incorrectas

**Dado** que ingreso credenciales incorrectas
**Cuando** hago click en "Iniciar sesión"
**Entonces** debería ver un mensaje:
- "Email o contraseña incorrectos"
**Y** los campos no deberían limpiarse
**Y** debería poder intentar de nuevo

### AC-005: Email no verificado

**Dado** que mi cuenta no ha verificado el email
**Cuando** intento hacer login
**Entonces** debería ver un mensaje:
- "Por favor verifica tu email antes de iniciar sesión"
**Y** debería ver un botón "Reenviar email de verificación"

### AC-006: Cuenta bloqueada

**Dado** que mi cuenta ha sido bloqueada por seguridad
**Cuando** intento hacer login
**Entonces** debería ver un mensaje:
- "Tu cuenta ha sido bloqueada. Contacta soporte."

### AC-007: Recordarme

**Dado** que marqué la opción "Recordarme"
**Cuando** inicio sesión exitosamente
**Entonces** el token debería tener una duración de 30 días
**Y** cuando cierre el navegador y vuelva a abrir
**Entonces** debería seguir con sesión activa

### AC-008: Rate limiting

**Dado** que he fallado 5 intentos de login
**Cuando** intento iniciar sesión nuevamente
**Entonces** debería ver un mensaje:
- "Demasiados intentos. Intenta en 15 minutos"

---

## Mockup

```
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│              🌟 Inicia sesión en Trading Platform                 │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ Email                                                │   │
│  │ ┌─────────────────────────────────────────────────┐ │   │
│  │ │ usuario@example.com                             │ │   │
│  │ └─────────────────────────────────────────────────┘ │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ Contraseña                                           │   │
│  │ ┌─────────────────────────────────────────────────┐ │   │
│  │ │ ••••••••••••                              👁   │ │   │
│  │ └─────────────────────────────────────────────────┘ │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ☐ Recordarme                  ¿Olvidaste tu contraseña?   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │               Iniciar sesión                         │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ─────────────────── O continúa con ───────────────────    │
│                                                             │
│  [Google] [Facebook] [X] [Apple] [GitHub]                  │
│                                                             │
│  ¿No tienes cuenta? Regístrate                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

---

## Tareas Técnicas

### Database (DB)

- [ ] Crear tabla `login_attempts` para rate limiting
  ```sql
  CREATE TABLE login_attempts (
    id UUID PRIMARY KEY,
    email VARCHAR(255),
    ip_address VARCHAR(45),
    attempt_time TIMESTAMP,
    success BOOLEAN,
    created_at TIMESTAMP DEFAULT NOW()
  );
  ```
- [ ] Índice en `email` y `attempt_time`

### Backend (BE)

- [ ] Endpoint `POST /api/v1/auth/login`
  - Validación de entrada con Zod
  - Verificar email verificado
  - Verificar cuenta no bloqueada
  - Comparar hash con bcrypt
  - Generar JWT token
  - Rate limiting (5 intentos / 15 min)
  - Logging de intentos
- [ ] Service `AuthService.login()`
- [ ] Middleware de rate limiting
- [ ] Tests unitarios (8 casos)
- [ ] Tests de integración (5 escenarios)

### Frontend (FE)

- [ ] Componente `apps/frontend/src/modules/auth/pages/Login.tsx`
- [ ] Form validation con React Hook Form + Zod
- [ ] Estado de loading durante autenticación
- [ ] Manejo de errores específicos
- [ ] Almacenamiento de token en localStorage/sessionStorage
- [ ] Redirección post-login
- [ ] Tests con React Testing Library (6 casos)

### Testing (QA)

- [ ] E2E: Login exitoso (Playwright)
- [ ] E2E: Credenciales incorrectas
- [ ] E2E: Email no verificado
- [ ] E2E: Rate limiting
- [ ] E2E: Recordarme funcionalidad
- [ ] Test de seguridad: SQL injection
- [ ] Test de seguridad: XSS
- [ ] Performance: < 500ms response time

---

## Dependencias

- **Bloqueantes:**
  - US-AUTH-001: Necesita usuarios registrados para poder hacer login

- **Deseables:**
  - US-AUTH-011: Para el flujo de "¿Olvidaste tu contraseña?"

---

## Definition of Ready (DoR)

- [ ] Mockups aprobados por UX
- [ ] Esquema de base de datos revisado
- [ ] API contract definido
- [ ] Criterios de aceptación claros
- [ ] Estimación acordada por el equipo

---

## Definition of Done (DoD)

- [ ] Código implementado y revisado (code review)
- [ ] Tests unitarios con 80%+ cobertura
- [ ] Tests de integración pasando
- [ ] Tests E2E implementados
- [ ] Documentación API actualizada
- [ ] Rate limiting configurado
- [ ] Logs implementados
- [ ] Seguridad validada (OWASP)
- [ ] QA aprobado en staging
- [ ] Deploy a producción exitoso

---

## Notas Técnicas

### JWT Token Structure

```json
{
  "sub": "user-id",
  "email": "user@example.com",
  "role": "user",
  "iat": 1234567890,
  "exp": 1234567890
}
```

### Rate Limiting Strategy

- 5 intentos fallidos por email
- Ventana de 15 minutos
- Reset después de login exitoso
- Bloqueo temporal, no permanente

### Security Considerations

- HTTPS obligatorio
- Password no visible en logs
- Tokens con expiración
- CSRF protection
- Content-Security-Policy headers

---

## Requerimientos Relacionados

- [RF-AUTH-002: Autenticación por Email](../requerimientos/RF-AUTH-002-email.md)

## Especificaciones Relacionadas

- [ET-AUTH-002: JWT Tokens](../especificaciones/ET-AUTH-002-jwt.md)
- [ET-AUTH-003: Database](../especificaciones/ET-AUTH-003-database.md)
