8.7 KiB
ADR-0004 — Pas d'authentification (réseau local uniquement)
- Statut : accepted
- Date : 2026-01-27
Contexte
HomeStock est une application web self-hosted destinée à un usage mono-utilisateur sur un réseau local domestique. La question de la sécurité d'accès se pose :
Contraintes du projet :
- Déploiement : Réseau local 10.0.0.0/22, pas d'exposition Internet prévue
- Utilisateurs : Mono-utilisateur (propriétaire du domicile)
- Données : Inventaire personnel, factures (non sensibles au sens RGPD)
- Accès physique : Réseau domestique, appareils de confiance uniquement
Questions à résoudre :
- Faut-il implémenter un système d'authentification (login/password) ?
- Si oui, quel niveau de sécurité est nécessaire ?
- Quels sont les risques réels d'un accès non authentifié sur réseau local ?
L'authentification ajoute de la complexité (gestion sessions, hash passwords, UI login) et peut dégrader l'expérience utilisateur (saisie répétée de credentials) pour un bénéfice de sécurité potentiellement faible dans ce contexte.
Décision
Nous ne déployons PAS de système d'authentification pour le MVP. L'application est accessible librement sur le réseau local sans login ni password.
Justification
- Périmètre réseau contrôlé : Réseau domestique 10.0.0.0/22, tous les appareils sont de confiance
- Pas d'exposition Internet : Application non accessible depuis l'extérieur, pas de port forwarding
- Mono-utilisateur : Pas de besoin de gestion de sessions ou de rôles
- Simplicité UX : Accès immédiat à l'application, pas de friction login
- Données non critiques : Inventaire domestique et factures, pas de données bancaires ou médicales
Périmètre de sécurité
- ✅ Réseau local uniquement : Application bind sur IP privée, pas 0.0.0.0
- ✅ HTTPS optionnel : TLS pour chiffrement en transit si certificat local disponible
- ✅ Firewall : Ports fermés en dehors du réseau local (configuration routeur)
- ❌ Pas de login/password : Accès direct à l'application
- ❌ Pas de sessions : Pas de gestion de tokens ou cookies d'authentification
- ❌ Pas de RBAC : Pas de rôles ou permissions (mono-utilisateur)
Configuration réseau recommandée
# docker-compose.yml
services:
backend:
ports:
- "10.0.0.X:8000:8000" # Bind IP privée uniquement, pas 0.0.0.0:8000
environment:
- ALLOWED_HOSTS=10.0.0.0/22 # Whitelist réseau local
Alternatives considérées
1. Authentification basique (login/password)
Description : Page de connexion avec username/password, session cookie
Avantages :
- ✅ Protection contre accès non autorisé sur réseau local
- ✅ Traçabilité des accès (logs)
- ✅ Possibilité multi-utilisateurs future facilitée
Inconvénients :
- ❌ Complexité additionnelle (hash passwords, sessions, CSRF, refresh tokens)
- ❌ UX dégradée (saisie credentials à chaque accès)
- ❌ Gestion mot de passe oublié nécessaire
- ❌ Sécurité illusoire si appareil compromis (cookies volés)
Verdict : ❌ Rejeté pour MVP - Bénéfice limité sur réseau local de confiance, complexité injustifiée
2. Authentification par IP (whitelist)
Description : Autoriser uniquement certaines IPs du réseau local
Avantages :
- ✅ Simple à implémenter (middleware FastAPI)
- ✅ Pas d'UI login
Inconvénients :
- ❌ Gestion fastidieuse des IPs autorisées
- ❌ DHCP complique le suivi (IPs dynamiques)
- ❌ Pas de granularité utilisateur
Verdict : ❌ Rejeté - Complexité sans bénéfice majeur, réseau déjà isolé
3. Authentification par certificat client (mTLS)
Description : Certificats X.509 pour authentifier les appareils
Avantages :
- ✅ Sécurité forte
- ✅ Pas de password à mémoriser
Inconvénients :
- ❌ Complexité extrême (PKI, distribution certificats)
- ❌ Configuration browser complexe
- ❌ Totalement surdimensionné pour le cas d'usage
Verdict : ❌ Rejeté - Overkill absolu
4. Pas d'authentification (notre choix)
Description : Accès libre sur réseau local
Avantages :
- ✅ Simplicité maximale (pas de code auth)
- ✅ UX optimale (accès instantané)
- ✅ Maintenance réduite
- ✅ Adapté au contexte mono-utilisateur réseau local
Inconvénients :
- ⚠️ Accès libre pour tout appareil sur réseau local
- ⚠️ Pas de traçabilité utilisateur
- ⚠️ Si exposition Internet accidentelle = vulnérabilité
Verdict : ✅ Choisi - Solution adaptée au contexte avec mitigations appropriées
Conséquences
Positives
- Simplicité code : Pas de code d'authentification, sessions, CSRF protection
- UX fluide : Accès immédiat, pas de friction login
- Pas de gestion passwords : Pas de hash, reset password, rotation
- Maintenance réduite : Pas de vulnérabilités auth à monitorer (OWASP Top 10)
- Performance : Pas de vérification session sur chaque requête
Négatives et risques
- Exposition accidentelle Internet : Si port forwarding activé par erreur → accès public
- Appareil compromis sur réseau : Malware sur laptop/smartphone pourrait accéder à l'app
- Visiteurs réseau : Invités connectés au WiFi domestique peuvent accéder à l'app
- Pas de traçabilité : Impossible de savoir qui a modifié/supprimé des données
Mitigations implémentées
- Bind IP privée uniquement : Backend écoute sur 10.0.0.X:8000, pas 0.0.0.0
- Firewall routeur : Ports 8000/5173 fermés en WAN, ouverts LAN uniquement
- HTTPS optionnel : Certificat auto-signé pour chiffrement en transit
- Logging applicatif : Logs des actions (créer/modifier/supprimer items) avec IP source
- Backup régulier : Scripts de backup pour récupération en cas d'actions malveillantes
- Documentation claire : Avertissement dans README sur importance isolation réseau
Mitigations à envisager (post-MVP)
- Mode "invité" simple : Code PIN basique si besoin de partager l'accès temporairement
- Alerte exposition : Check au startup si l'app est accessible depuis Internet (API externe)
- Read-only mode : Mode lecture seule pour appareils moins fiables
Impacts techniques
Code simplifié
Pas de code d'authentification signifie :
- Pas de modèle
Useren base - Pas de hash passwords (bcrypt, argon2)
- Pas de gestion sessions/tokens
- Pas de middleware CSRF protection
- Pas d'endpoints
/login,/logout,/register - Pas d'UI login/signup
Configuration Docker
# docker-compose.yml
services:
backend:
ports:
- "10.0.0.50:8000:8000" # IP privée fixe uniquement
environment:
- ALLOWED_ORIGINS=http://10.0.0.50:5173,http://localhost:5173
- CORS_ALLOW_CREDENTIALS=false # Pas de cookies
Logging renforcé
Même sans auth, logger les actions pour traçabilité :
# Exemple log
logger.info(
"Item created",
extra={
"item_id": item.id,
"item_name": item.name,
"source_ip": request.client.host,
"user_agent": request.headers.get("user-agent")
}
)
Évolution future
Si exposition Internet devient nécessaire (accès depuis extérieur) :
- Ajouter authentification : Login simple (username/password) + session cookie
- Reverse proxy avec auth : Traefik BasicAuth ou OAuth2 Proxy
- VPN : Accès via WireGuard/Tailscale (recommandé)
- Cloudflare Access : Zero-trust avec auth externe
Notes
Cette décision est contextuelle et adaptée à HomeStock :
- ✅ Réseau local domestique contrôlé
- ✅ Mono-utilisateur
- ✅ Données non critiques
Elle serait inappropriée pour :
- ❌ Application exposée sur Internet
- ❌ Multi-utilisateurs
- ❌ Données sensibles (bancaires, médicales, secrets)
- ❌ Environnement professionnel
Analogie : C'est comme ne pas mettre de serrure sur la porte de sa chambre dans sa propre maison (réseau local) vs mettre une serrure sur la porte d'entrée (exposition Internet).
Si le contexte change (exposition Internet, ajout utilisateurs), cette décision devra être revisitée et l'authentification ajoutée. L'architecture modulaire (ADR-0002) facilite cet ajout futur sans refonte majeure.
Principe appliqué : "Security proportionate to risk" - Ne pas sur-sécuriser quand le risque est faible et contrôlé.
Contributeurs : Gilles (décideur) + Claude Code (architecte)
Avertissement important : Cette configuration est sécurisée UNIQUEMENT si le réseau local est isolé d'Internet. Vérifier régulièrement que :
- Aucun port forwarding n'est configuré sur le routeur
- Aucun service de tunnel (ngrok, etc.) n'est actif
- Le firewall du routeur est correctement configuré