La sécurité n'est pas une fonctionnalité, c'est un prérequis
En 2025, les cyberattaques contre les applications SaaS sont en hausse constante. Injection SQL, XSS, CSRF, credential stuffing — les vecteurs d'attaque sont nombreux et les conséquences d'une faille sont désastreuses : perte de données, amendes RGPD, réputation détruite.
La bonne nouvelle ? La majorité de ces attaques peuvent être prévenues avec des pratiques établies. Boilerplate-Stack intègre ces protections nativement, conformément aux recommandations OWASP.
Magic links vs mots de passe : le bon choix en 2025
Les mots de passe sont le maillon faible de la sécurité web depuis des décennies :
- Les utilisateurs réutilisent les mêmes mots de passe partout
- Les bases de données de mots de passe sont régulièrement compromises
- Le stockage sécurisé (bcrypt, argon2) ne protège pas contre le phishing
- La gestion du mot de passe oublié est un vecteur d'attaque en soi
Les magic links éliminent tous ces problèmes :
- Pas de mot de passe à stocker — rien à compromettre dans votre base
- Authentification par email — si l'attaquant a accès à l'email, il a déjà accès à tout via « mot de passe oublié »
- Expérience utilisateur supérieure — un clic, pas de mémorisation
- Compatible avec l'OAuth — ajoutez Google, GitHub en complément
Dans Boilerplate-Stack, les magic links sont envoyés via Brevo avec des templates personnalisés en français et en anglais.
Authentification côté serveur : getUser() vs getSession()
C'est l'erreur la plus dangereuse et la plus courante en développement Supabase :
// DANGEREUX — la session peut être falsifiée côté client
const { data: { session } } = await supabase.auth.getSession()
// SÉCURISÉ — valide le token auprès de Supabase
const { data: { user } } = await supabase.auth.getUser()getSession() lit simplement le cookie sans le valider. Un attaquant peut forger un cookie de session. getUser() envoie le token à Supabase pour vérification. Utilisez toujours getUser() côté serveur.
Row Level Security (RLS) : votre dernière ligne de défense
La RLS PostgreSQL est le mécanisme de sécurité le plus puissant dans une architecture Supabase. Elle s'applique au niveau de la base de données, indépendamment du code applicatif.
-- Chaque table filtrée par membership
CREATE POLICY "members_access" ON chat_sessions FOR ALL
USING (EXISTS (
SELECT 1 FROM memberships
WHERE memberships.account_id = chat_sessions.account_id
AND memberships.user_id = auth.uid()
));Avantages de la RLS :
- Défense en profondeur : même si une route API est compromise, les données restent protégées
- Impossible à contourner : s'applique à toutes les requêtes, y compris les jointures
- Performance : PostgreSQL optimise les politiques RLS comme des WHERE classiques
OWASP Top 10 : les protections implémentées
1. Injection (SQL, NoSQL, OS)
Supabase utilise des requêtes paramétrées nativement. Jamais de concaténation de strings SQL. Validation Zod sur tous les inputs.
2. Authentification défaillante
Magic links + OAuth. Pas de mots de passe. Rate limiting strict sur les endpoints d'auth (5 requêtes/minute).
3. Exposition de données sensibles
RLS sur chaque table. Sélection explicite des colonnes (.select()). Jamais de SELECT * exposé à l'utilisateur.
4. XXE (Entités externes XML)
Non applicable — pas de parsing XML. API JSON uniquement.
5. Contrôle d'accès défaillant
Middleware de sécurité API avec niveaux (apiSecurity.public(), .authenticated(), .admin()). Vérification de rôle et de membership.
6. Mauvaise configuration de sécurité
Headers HTTP stricts dans next.config.ts :
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Strict-Transport-Security: max-age=630720007. Cross-Site Scripting (XSS)
React échappe par défaut. Content Security Policy stricte. Sanitisation des inputs avec sanitize.html().
8. Désérialisation non sécurisée
Validation Zod sur toutes les entrées. Pas de eval(), pas de désérialisation arbitraire.
9. Composants vulnérables connus
Dépendances à jour. Audit régulier avec npm audit.
10. Journalisation insuffisante
Table admin_logs pour les actions administratives. ai_requests pour le suivi d'utilisation. credit_transactions pour l'audit financier.
Rate limiting multi-niveaux
Le rate limiting est essentiel pour prévenir les abus :
strict: 5/min — opérations sensibles (auth, suppression)
standard: 30/min — API générale
relaxed: 100/min — lectures publiques
ai: 10/min — requêtes IA
contact: 3/min — formulaire de contact
webhook: 100/min — webhooks externesImplémenté avec Upstash Redis en production, avec un fallback en mémoire pour le développement.
Protection CSRF
Le pattern Double Submit Cookie protège contre les attaques CSRF :
- Un token aléatoire est généré et stocké dans un cookie httpOnly
- Le même token est envoyé dans le header de la requête
- Le serveur vérifie que les deux correspondent
- Validation additionnelle de l'Origin et du Referer
Protection contre les bots
Cloudflare Turnstile est intégré sur les formulaires sensibles :
- Formulaire de contact
- Inscription newsletter
- Page de connexion (optionnel)
Turnstile est invisible pour l'utilisateur dans la plupart des cas, contrairement aux CAPTCHA traditionnels.
Ne partez pas de zéro pour la sécurité
Implémenter correctement toutes ces couches de sécurité prend des semaines et nécessite une expertise pointue. Une seule erreur peut compromettre l'ensemble.
Boilerplate-Stack intègre toutes ces protections nativement. Chaque route API, chaque composant, chaque requête base de données est sécurisé selon les meilleures pratiques OWASP.
Découvrez l'implémentation complète sur boilerplate-stack.com et lancez votre SaaS avec une sécurité de niveau professionnel dès le premier jour.