# Component: PasswordService ## Responsabilidad Gestionar el cambio de contraseña de usuarios autenticados. Validar contraseña actual, verificar requisitos de seguridad de la nueva contraseña, y invalidar sesiones existentes. ## Tipo - [x] Microservicio - [ ] Library/Biblioteca - [ ] Shared Component - [ ] External Integration ## Interfaces ### API REST ``` POST /api/v1/users/{user_id}/change-password Authorization: Bearer Input: { "current_password": string, "new_password": string, "confirm_password": string } Output: { "success": true, "message": "Contraseña actualizada" } Errors: - 400: Validation errors (password too weak, mismatch) - 401: Current password incorrect - 403: Not owner - 404: User not found ``` ## Dependencias | Servicio/Biblioteca | Tipo | Notas | |---------------------|------|-------| | PostgreSQL | Database | Almacenamiento de usuarios | | Redis | Cache | Invalidation de sesiones | | AuthService | Internal | Verificación de token | ## Validaciones de contraseña | Regla | Requisito | Mensaje de error | |-------|-----------|------------------| | Longitud mínima | 8 caracteres | "La contraseña debe tener al menos 8 caracteres" | | Longitud máxima | 128 caracteres | "La contraseña debe tener máximo 128 caracteres" | | Mayúsculas | Al menos 1 | "La contraseña debe contener al menos una mayúscula" | | Minúsculas | Al menos 1 | "La contraseña debe contener al menos una minúscula" | | Números | Al menos 1 | "La contraseña debe contener al menos un número" | | Caracteres especiales | Al menos 1 | "La contraseña debe contener al menos un carácter especial (!@#$%^&*...)" | | No usar password anterior | Diferente | "La nueva contraseña no puede ser igual a la anterior" | ## Límites ### Alcance - ✅ Cambio de contraseña con validación - ✅ Requisitos de seguridad - ✅ Invalidación de sesiones - ❌ NO maneja recuperación de contraseña (ver ForgotPasswordService) - ❌ NO maneja reset forzado por admin (ver AdminService) ### Constraints - Rate limit: 5 intentos por hora por usuario - Timeout máximo: 1 segundo - Máximo 3 passwords válidas en historial (evitar reutilización inmediata) ## Criterios de éxito | Criterio | Métrica | Target | |----------|---------|--------| | Disponibilidad | uptime | 99.9% | | Latencia | p99 change_password | < 500ms | | Rate limit | blocked attempts | 100% | | Sesiones invalidées | después de cambio | 100% | ## Diagrama ```mermaid graph LR A[Client] -->|POST /change-password| B[PasswordService] B -->|validate current| C[(PostgreSQL)] B -->|validate new| D[PasswordValidator] D -->|strong enough?| E{Valid} E -->|yes| F[Hash + Save] E -->|no| G[Return error] F -->|invalidate| H[(Redis)] H -->|remove sessions| I[All user tokens] ``` ## Estados | Estado | Trigger | Acción | |--------|---------|--------| | Initial | started | Connect to DB | | Ready | db_connected | Accept requests | | RateLimited | >5 attempts/hour | Return 429 | | Error | db_failure | Return 503 | ## Seguridad - **Password hashing**: bcrypt, cost 12 (nuevo), verificar contra hash existente - **Timing attack prevention**: usar constant-time comparison - **Rate limiting**: 5 req/hour por user_id - **Sesiones**: invalidar TODAS las sesiones del usuario tras cambio - **Logs**: NO registrar passwords, solo intentos fallidos (user_id anonymized) ## Observabilidad - Metrics: `password_change_total`, `password_change_failed`, `password_change_latency` - Logs: structured JSON con request_id - Traces: OpenTelemetry span por request ## Tests BDD - Ver `spec/bdd/features/password/change-password.feature`