mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-04-06 13:31:43 +02:00
231 lines
8.3 KiB
Markdown
231 lines
8.3 KiB
Markdown
# Backend — Patterns : Auth
|
|
|
|
> Extrait de la base de connaissance Lead_tech. Voir `knowledge/backend/patterns/README.md` pour l'index complet.
|
|
|
|
---
|
|
|
|
<a id="pattern-format-derreur-api-standardise"></a>
|
|
|
|
## 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)
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
---
|
|
|
|
<a id="pattern-middleware-correlation-requestid-traceid"></a>
|
|
|
|
## 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)
|
|
|
|
```txt
|
|
- 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
|
|
|
|
---
|
|
|
|
<a id="pattern-anti-enumeration-auth-email"></a>
|
|
## 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)
|
|
|
|
```txt
|
|
- 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
|
|
|
|
---
|
|
|
|
<a id="pattern-token-usage-unique"></a>
|
|
## 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)
|
|
|
|
```txt
|
|
- 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
|
|
|
|
---
|
|
|
|
<a id="pattern-autorisation-interne-minimale"></a>
|
|
|
|
## 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)
|
|
|
|
```txt
|
|
- 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
|
|
|
|
---
|
|
|
|
<a id="pattern-auth-operations-atomiques"></a>
|
|
## 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 :
|
|
- `$transaction` Prisma 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)
|
|
|
|
```typescript
|
|
// 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`
|
|
- [ ] `P2025` absorbé 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
|