Auth Module Implementation - Notes techniques¶
Contexte¶
Implémentation de l'authentification JWT pour le projet gest-recettes-depenses selon le pattern DDD strict du GUIDE_ARCHITECTURE_DDD.md.
Architecture implémentée¶
Layers¶
- Domain : AuthExceptions, AuthDTO, auth.schemas (constantes)
- Application : ILoginUseCase/IRegisterUseCase interfaces avec DonnesXxx/ResultatXxx/ CodeErreurXxx
- Infrastructure : AuthService (JWT+bcrypt), ServiceValidationAuth (Zod), AuthModule (DI)
- Interface-Adapters : Handlers (extends BaseActionHandler), Controllers, Routes
Problèmes rencontrés¶
1. Accès au mot de passe haché (RÉSOLU)¶
Le LoginUseCase doit comparer le mot de passe en clair avec le hash. L'IUtilisateurRepository ne fournit pas le hash dans le DTO (pas de champ motDePasse).
Solution implémentée : Méthode obtenirMotDePasseParEmail(email: string) ajoutée dans l'interface et l'implémentation Prisma :
// IUtilisateurRepository.ts
obtenirMotDePasseParEmail(email: string): Promise<string | null>;
// UtilisateurRepositoryPrisma.ts
async obtenirMotDePasseParEmail(email: string): Promise<string | null> {
const result = await this.prisma.utilisateur.findUnique({
where: { email },
select: { motDePasse: true }
});
return result?.motDePasse || null;
}
Cette solution respecte le pattern DDD : le UseCase n'a accès qu'aux interfaces, jamais aux implémentations concrètes.
2. Type expiresIn pour jsonwebtoken¶
// ❌ Erreur TS2769
return sign(payload, secret, { expiresIn: string });
// ✅ Solution
const options: SignOptions = { expiresIn: this.jwtExpiresIn as any };
return sign(payload, this.jwtSecret, options);
3. Convention d'imports¶
Tous les imports utilisent le path alias @/ configuré dans tsconfig.json.
Points forts du pattern DDD¶
| Aspect | Bonne pratique |
|---|---|
| Exceptions | extends ErreurMetier, union types pour codes |
| DTOs | versObjetPlainPublic() pour HTTP, jamais versObjetPlain() |
| UseCase | 5 étapes: validation → logique → audit → résultat → erreur |
| DI | Ordre strict: repos → services → usecases → controllers |
| Handlers | Extends BaseActionHandler, 3 méthodes publiques max |
Recommandations architecturelles¶
- Extraire AuthMiddleware dans
shared/infrastructure/middleware/(actuellement inline dans server.ts) - ~~Ajouter méthode repository pour récupérer le hash mot de passe~~ ✅ TERMINÉ
- Implémenter 2FA avec
otplib(déjà dans package.json, champdeuxFacteursActiveexistant) - Rate limiting spécifique pour
/auth/loginet/auth/register(déjà configuré viarateLimit: 'auth')
Fichiers créés¶
Modules/Auth/
├── domain/exceptions/AuthExceptions.ts
├── domain/schemas/auth.schemas.ts
├── domain/types/AuthDTO.ts
├── application/interfaces/ILoginUseCase.ts
├── application/interfaces/IRegisterUseCase.ts
├── application/usecases/LoginUseCase.ts
├── application/usecases/RegisterUseCase.ts
├── infrastructure/di/AuthModule.ts
├── infrastructure/services/AuthService.ts
├── infrastructure/schemas/zod/login.schemas.ts
├── infrastructure/schemas/zod/register.schemas.ts
├── infrastructure/services/validation/ServiceValidationAuth.ts
├── interface-adapters/controllers/AuthModuleController.ts
├── interface-adapters/controllers/LoginController.ts
├── interface-adapters/controllers/RegisterController.ts
├── interface-adapters/handlers/LoginHandler.ts
├── interface-adapters/handlers/RegisterHandler.ts
├── interface-adapters/routes/auth.module.routes.ts
└── index.ts
Liens liés¶
- GUIDE_ARCHITECTURE_DDD
- [[raport-architecture-ddd]]
📝 Implémentation Audit (2026-05-31)¶
Modèle Prisma ajouté :
model AuditLog {
id String @id @default(uuid())
utilisateurId String
action String @db.VarChar(100)
ressource String @db.VarChar(100)
ressourceId String?
details String? @db.Text
resultat String? @db.VarChar(10)
adresseIP String? @db.VarChar(45)
userAgent String? @db.VarChar(500)
dateCreation DateTime @default(now())
@@index([utilisateurId])
@@index([action])
@@index([dateCreation])
@@map("audit_logs")
}
Fichiers créés :
- shared/domain/interfaces/repositories/IAuditLogRepository.ts (existait déjà)
- shared/infrastructure/repositories/prisma/AuditLogRepositoryPrisma.ts
Intégration :
- AuthModule.ts → injecte AuditLogRepositoryPrisma
- LoginUseCase.ts → utilise auditLogRepository.creer() pour journaliser
- RegisterUseCase.ts → utilise auditLogRepository.creer() pour journaliser
⚠️ À faire : Exécuter npx prisma generate pour régénérer le client avec le modèle AuditLog.