ADR 0006 : Sécurité du code PIN - format de mot de passe et rate limiting (v1)
- Statut : Accepté
- Décideurs : Marco (Commanditaire), Julien (Commanditaire), Seer (Développeur)
- Date : 8 juillet 2026
Contexte et Problème
Avec Supabase Auth natif (ADR 0002), le PIN à 4 chiffres est le mot de passe du compte. Deux contraintes s'opposent :
- Supabase impose un mot de passe d'au moins 6 caractères ; un PIN en fait 4.
- Un PIN à 4 chiffres n'offre que 10 000 combinaisons → faible entropie, vulnérable à la force brute si le nombre d'essais n'est pas limité.
Il faut donc (a) rendre le PIN acceptable par Supabase et (b) protéger réellement la connexion, sans attendre la solution complète (pepper) traitée séparément en ADR 0007.
Facteurs de Décision
- Compatibilité : respecter le minimum de 6 caractères de Supabase.
- Protection réelle : la vraie menace d'un PIN à 4 chiffres est le brute-force en ligne.
- Réversibilité/évolutivité : ne pas se fermer la porte à une vraie dérivation sécurisée (pepper) plus tard.
- Livrable immédiat : solution déployable maintenant, sans refonte des flux client.
Options Envisagées
Option A : Allonger le mot de passe par un suffixe fixe, sans autre mesure
password = pin + '_myjholding'.
- Avantage : trivial ; satisfait le minimum de 6 caractères.
- Inconvénient : n'ajoute aucune sécurité (suffixe constant, visible côté client) ; ne protège pas du brute-force.
Option B : PIN à 6 chiffres
Passer les codes à 6 chiffres (1 000 000 combinaisons, ≥ 6 caractères nativement).
- Avantage : plus d'entropie, plus besoin de suffixe.
- Inconvénient : décision produit - le brief impose 4 chiffres ; impacte tous les utilisateurs.
Option C : Suffixe (remplissage) centralisé + rate limiting (Recommandée)
- Centraliser la dérivation dans
lib/pinPassword.js(pinToPassword) - le suffixe reste un simple remplissage assumé comme non secret, mais isolé en un seul point (le futur pepper ne changera que ce fichier). - Ajouter un rate limiting sur
/api/login(lib/rateLimiter.js) : 5 échecs → verrouillage 15 min par membre, remis à zéro à la réussite ; réponse HTTP 429.
- Avantage : protège réellement contre le brute-force en ligne (le point faible du PIN à 4 chiffres) ; prépare proprement le pepper (v2) ; aucun changement des flux client.
- Inconvénient : l'état du rate limiter est en mémoire → « best-effort » en serverless (Netlify) ; le suffixe reste non secret.
Décision Retenue
L'Option C a été retenue.
Justification
Le point faible d'un PIN à 4 chiffres n'est pas la longueur du mot de passe mais le nombre d'essais autorisés : le rate limiting est donc la mesure à fort impact, livrable immédiatement et 100 % côté serveur. La centralisation de pinToPassword évite de disperser le suffixe et fait du passage au pepper (ADR 0007) un changement d'un seul fichier. Le PIN à 6 chiffres (Option B) reste une décision produit non tranchée.
Conséquences
Positives
- Brute-force en ligne bloqué (5 tentatives / 15 min).
- Dérivation du mot de passe centralisée et prête pour le pepper.
- Déployable sans toucher aux parcours utilisateur ; couvert par
npm run test:login.
Négatives
- Le suffixe n'apporte pas de sécurité en soi (assumé, documenté).
- Rate limiter en mémoire : protection dégradée en serverless → durcissement (compteur persistant) prévu en ADR 0007.
- Un changement de format de mot de passe impose de rejouer
npm run reset:pins.
