mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-04-06 21:41:42 +02:00
8.3 KiB
8.3 KiB
Backend — Patterns : Auth
Extrait de la base de connaissance Lead_tech. Voir
knowledge/backend/patterns/README.mdpour l'index complet.
Pattern : Format d'erreur API standardisé
- Objectif : fournir des erreurs prévisibles, exploitables et cohérentes pour tous les clients.
- Contexte : API consommée par front-end, automatisations ou intégrations externes.
- Quand l'utiliser : dès qu'une API est exposée à autre chose qu'un usage interne trivial.
- Quand l'éviter : jamais.
- Avantage :
- Debug plus rapide
- UX maîtrisée côté client
- Observabilité améliorée
- Limites / vigilance :
- Discipline requise pour éviter les formats ad hoc
- Validé le : 25-01-2026
- Contexte technique : API HTTP agnostique
Implémentation (exemple minimal)
{
"error": {
"code": "USER_NOT_FOUND",
"message": "Utilisateur introuvable",
"requestId": "abc-123"
}
}
Checklist
- Codes HTTP cohérents (4xx / 5xx)
- Codes d'erreur applicatifs stables
- Message utilisateur non technique
- requestId présent
Pattern : Middleware de corrélation (requestId / traceId)
- Objectif : relier chaque requête aux logs et erreurs associées.
- Contexte : toute API ou service exposé.
- Quand l'utiliser : systématiquement en production.
- Quand l'éviter : jamais.
- Avantage :
- MTTR réduit drastiquement
- Debug cross-services possible
- Limites / vigilance :
- Doit être propagé partout (logs, erreurs, appels sortants)
- Validé le : 25-01-2026
- Contexte technique : Backend agnostique (HTTP)
Implémentation (exemple minimal)
- Générer un requestId à l'entrée si absent
- Le propager dans le contexte de requête
- L'inclure dans chaque log et réponse d'erreur
Checklist
- requestId généré ou repris d'un header existant
- Présent dans tous les logs
- Présent dans les erreurs retournées
Pattern : Anti-énumération sur endpoints auth liés à un email
- Objectif : empêcher qu'un endpoint auth révèle si un compte existe, n'existe pas ou n'est pas éligible.
- Contexte : reset de mot de passe, invitation, vérification de compte, login ou tout flux qui part d'un email utilisateur.
- Quand l'utiliser : dès qu'une requête auth touche un identifiant de type email.
- Quand l'éviter : jamais sur une surface exposée.
- Avantage :
- réduit la fuite d'information sur les comptes existants
- homogénéise les réponses côté client
- se combine bien avec les garde-fous anti-abus
- Limites / vigilance :
- ne protège pas seul contre le brute-force, à combiner avec du rate-limiting
- les logs internes doivent conserver la vraie cause sans l'exposer au client
- Validé le : 16-03-2026
- Contexte technique : Node.js / auth applicative / API HTTP
Implémentation (exemple minimal)
- retourner la même réponse HTTP 200 qu'un compte existe ou non
- ne jamais distinguer "email inconnu", "email connu" ou "compte OAuth-only" dans la réponse
- journaliser la cause réelle côté serveur
- ajouter un rate-limiting basé sur email + IP
Checklist
- Réponse client uniforme pour les cas compte connu/inconnu/non éligible
- Aucune fuite d'existence dans le message ou le code d'erreur
- Rate-limiting présent sur les endpoints exposés
- Logs internes exploitables
Pattern : Token à usage unique — génération, hash et invalidation atomique
- Objectif : standardiser la création et la consommation de tokens sensibles sans stocker de secret brut en base.
- Contexte : invitation, reset de mot de passe, vérification d'email, lien magique ou tout token one-shot.
- Quand l'utiliser : pour tout token à usage unique transmis à l'utilisateur.
- Quand l'éviter : sessions longues ou secrets devant être relus en clair côté serveur.
- Avantage :
- réduit l'impact d'une fuite de base
- garde des tokens URL-safe
- favorise une consommation atomique et réutilisable
- Limites / vigilance :
- la consommation doit rester atomique
- la politique d'expiration doit être explicite
- Validé le : 16-03-2026
- Contexte technique : Node.js
crypto/ Prisma / email ou URL signée
Implémentation (exemple minimal)
- générer le token avec `crypto.randomBytes(32).toString("base64url")`
- stocker uniquement le hash SHA-256 du token en base
- transmettre le token brut uniquement via URL ou email
- recalculer le hash côté serveur lors de la consommation
- invalider le token dans une transaction atomique après usage
Checklist
- Token brut jamais persisté en base
- Hash recalculé côté serveur pour la vérification
- Expiration explicite
- Invalidation atomique après consommation
Pattern : Autorisation interne minimale sans RBAC complet
- Objectif : sécuriser une capacité interne sensible sans ouvrir trop tôt un chantier RBAC complet.
- Contexte : application avec peu de rôles, besoin ponctuel d'une capacité admin ou opérateur clairement identifiée.
- Quand l'utiliser : quand une story métier demande un pouvoir interne limité mais réel.
- Quand l'éviter : si les permissions deviennent nombreuses, hiérarchiques ou contextuelles.
- Avantage :
- sécurisation rapide et lisible d'une capacité sensible
- source de vérité backend explicite
- chemin d'évolution propre vers un RBAC plus complet
- Limites / vigilance :
- ne pas laisser proliférer des rôles ad hoc non gouvernés
- ne remplace pas un vrai modèle de permissions si le domaine grossit
- Validé le : 10-03-2026
- Contexte technique : NestJS / auth par session ou JWT / API métier interne
Implémentation (exemple minimal)
- introduire un enum de rôle minimal côté backend (ex. USER | ADMIN)
- propager ce rôle dans la session ou le token d'auth
- créer un décorateur + guard dédiés pour la capacité sensible
- interdire les booléens front, emails hardcodés ou `if` dispersés dans les contrôleurs
Checklist
- Le rôle vit dans la source de vérité backend
- Le rôle est propagé dans le mécanisme d'auth existant
- Les endpoints sensibles passent par un guard dédié
- Aucun contrôle d'accès critique n'est piloté par le front
- Le passage à RBAC reste possible sans casser le contrat existant
Pattern : Opérations auth sensibles — atomiques, idempotentes et cohérentes
- Objectif : garantir que les opérations multi-étapes auth (reset, logout, révocation) ne laissent jamais un état incohérent.
- Contexte : tout flux auth qui combine plusieurs writes : hash de mot de passe, invalidation de token, suppression de session.
- Quand l'utiliser : systématiquement sur toute opération qui touche plusieurs tables auth en séquence.
- Quand l'éviter : opérations de lecture pure.
- Avantage :
- pas de token valide après reset de mot de passe si l'opération est interrompue
- suppression de session idempotente (P2025 absorbé silencieusement)
- comportement prévisible même en cas de retry ou de concurrence
- Limites / vigilance :
$transactionPrisma ne couvre pas les effets de bord réseau (email, cookies) — ces étapes restent hors transaction
- Validé le : 16-03-2026
- Contexte technique : Node.js / Prisma / auth par session ou token
Implémentation (exemple minimal)
// consumePasswordReset — atomique dans une transaction
await prisma.$transaction([
prisma.passwordResetToken.update({
where: { tokenHash },
data: { consumedAt: new Date() },
}),
prisma.user.update({
where: { id: userId },
data: { passwordHash: newHash },
}),
prisma.session.deleteMany({ where: { userId } }),
]);
// Suppression de session — idempotente (P2025 absorbé)
try {
await prisma.session.delete({ where: { sessionToken } });
} catch (err) {
if (err?.code !== 'P2025') throw err; // session déjà supprimée → OK
}
Checklist
- Toute opération hash + update + delete dans une
$transaction P2025absorbé silencieusement sur les suppressions de session- Effets de bord hors transaction documentés (cookie, email)
- Tests couvrant le cas d'une session déjà expirée