Changement d'email
Flow 2-step (request → confirm) avec code 6 chiffres, mot de passe ou code 2FA, anti-énumération.
Modifier l'email d'un compte exige une preuve de possession de la nouvelle
adresse (code 6 chiffres) et — pour les comptes credential — le mot de
passe actuel. Géré dans /account/settings → Profil → Changer.
Flow 2-step
POST /api/user/change-email { newEmail, password? }
→ envoie un code à `newEmail`
PATCH /api/user/change-email { code }
→ confirme + swap email + bump tokenVersion- Compte credential (a un password) →
passwordrequis avant l'envoi du code - Compte OAuth-only (pas de password) → seul le code email confirme
Anti-énumération
L'API renvoie { ok: true } même si l'email cible est déjà pris — pas de
fuite d'existence de compte. On stocke un token verifyToken dans tous
les cas mais on n'envoie le mail que si l'email n'est pas pris.
Le swap final vérifie de nouveau l'unicité (P2002 → 409). Une race
entre le request et le confirm est gérée proprement.
Hash du code
Le code 6 chiffres n'est jamais stocké en clair — on persiste
sha256(identifier:code) en DB. Un dump partiel ne suffit pas à finir
le change-email.
Bump tokenVersion
Sur swap réussi, tokenVersion: { increment: 1 } → tous les autres JWT
de ce user (mobile, autres navigateurs) sont invalidés au prochain
refresh. Sécurité supplémentaire au cas où la session courante n'est
pas la seule.
Anti-bruteforce
- Rate-limit IP : 5 requêtes / heure (
lib/rate-limit.ts) - Compteur d'essais sur le code : 5 max → token brûlé
- Code expire après 15 min
Audit
user.email_changed avec metadata.newEmail. Visible côté user dans
Activity log.