Politique de Sécurité - Better Auth Cloudflare
Politique de Sécurité - Better Auth Cloudflare
Documentation technique
Objet : Spécification politique de sécurité pour Better Auth Cloudflare
Type : Documentation Technique (DAT)
Couche : Couche 03 (Backend - Sécurité)
Emplacement : Configuration Better Auth + Variables d’environnement
Statut : DOC (Proposé)
1. Vue d’ensemble (DOC)
1.1. Description
Politique de sécurité complète pour l’implémentation de Better Auth Cloudflare, couvrant la gestion des secrets, la configuration des cookies, la protection CSRF, et les best practices de sécurité.
1.2. Objectif
- Définir la gestion sécurisée des secrets
- Spécifier la configuration des cookies
- Documenter les protections CSRF
- Établir les best practices de sécurité
2. Gestion des Secrets (CODE)
2.1. Secrets Requis1/2
Better Auth Secret :
- Utilisé pour signer les cookies et tokens
- Doit être une chaîne aléatoire de 32+ caractères
- Généré une fois et stocké de manière sécurisée
2.1. Secrets Requis2/2
Cloudflare Credentials :
CLOUDFLARE_ACCOUNT_ID: ID du compte CloudflareCLOUDFLARE_API_TOKEN: Token API avec permissions limitées
Database Credentials :
AUTH_DB_ID: ID de la base D1AUTH_KV_ID: ID du namespace KV
2.2. Génération des Secrets
# Générer Better Auth Secretnode -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Exemple de sortie:# a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z62.3. Stockage des Secrets1/2
Local Development :
# .env (jamais commité)BETTER_AUTH_SECRET=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6CLOUDFLARE_ACCOUNT_ID=your-account-idCLOUDFLARE_API_TOKEN=your-api-tokenAUTH_DB_ID=your-d1-database-idAUTH_KV_ID=4a990eb34db9430284b0961ac5d107dd2.3. Stockage des Secrets2/2
Production Cloudflare :
# Utiliser le script d'injection de secrets./@inject_secret_to_cloudflare.sh
# Ou via wrangler CLIwrangler secret put BETTER_AUTH_SECRETwrangler secret put CLOUDFLARE_API_TOKEN2.4. Rotation des Secrets1/2
Politique de rotation :
- Better Auth Secret : Rotation annuelle ou si compromis
- Cloudflare API Token : Rotation trimestrielle
- Database IDs : Pas de rotation (identifiants statiques)
2.4. Rotation des Secrets2/2
Procédure de rotation :
- Générer nouveau secret
- Mettre à jour .env local
- Tester en développement
- Déployer en production avec nouveau secret
- Surveiller les erreurs d’authentification
- Garder l’ancien secret en backup pendant 7 jours
3. Configuration des Cookies (CODE)
3.1. Configuration wrangler.jsonc avec Observabilité
Conformément aux recommandations Cloudflare, nous utilisons wrangler.jsonc avec observabilité activée :
{ "$schema": "node_modules/wrangler/config-schema.json", "name": "amn-dev", "compatibility_date": "2026-09-01", "compatibility_flags": ["nodejs_compat"],
"observability": { "enabled": true, "logs": { "head_sampling_rate": 1 }, "traces": { "enabled": true, "head_sampling_rate": 0.01 } }}3.2. Configuration Better Auth
export function createAuth(env: any) { return betterAuth({ ...withCloudflare( { d1: { db, options: { usePlural: true } }, kv: env.AUTH_KV }, { advanced: { cookiePrefix: "amn-auth", useSecureCookies: env.ENVIRONMENT === 'prod', sameSite: "lax", httpOnly: true }, session: { cookieCache: { maxAge: 5 * 60, // 5 minutes cache enabled: true } } } ) });}3.2. Attributs des Cookies
| Attribut | Valeur Dev | Valeur Prod | Description |
|---|---|---|---|
HttpOnly |
true |
true |
Inaccessible via JavaScript |
Secure |
false |
true |
HTTPS uniquement en prod |
SameSite |
lax |
lax |
Protection CSRF |
Path |
/ |
/ |
Disponible sur tout le site |
Max-Age |
604800 (7 days) |
604800 (7 days) |
Durée de vie |
3.3. Noms des Cookies
// Cookies générés par Better Auth avec prefix "amn-auth"amn-auth.session.token // Session tokenamn-auth.session.user // User data (si activé)4. Protection CSRF (CODE)
4.1. Better Auth CSRF Protection
Better Auth inclut une protection CSRF automatique via :
- Validation de l’origine des requêtes
- Vérification des headers
OriginetReferer - Tokens CSRF pour les requêtes state-changing
4.2. Configuration CSRF
export function createAuth(env: any) { return betterAuth({ ...withCloudflare( { d1: { db }, kv: env.AUTH_KV }, { advanced: { csrfProtection: { enabled: true, checkHost: true } } } ) });}4.3. Headers Requis
Pour les requêtes POST/PUT/DELETE :
fetch('/api/auth/sign-in', { method: 'POST', headers: { 'Content-Type': 'application/json', // Better Auth valide automatiquement Origin/Referer }, credentials: 'include'});5. Politique de Session (CODE)
5.1. Configuration Session
session: { expiresIn: 60 * 60 * 24 * 7, // 7 jours updateAge: 60 * 60 * 24, // Rafraîchissement quotidien cookieCache: { maxAge: 5 * 60, // Cache 5 minutes enabled: true }}5.2. Cycle de Vie Session
Login → Création session D1 → Cache KV → Cookie client ↓ Rafraîchissement quotidien (updateAge) ↓ Expiration après 7 jours (expiresIn) ↓ Logout → Suppression D1 + KV + Cookie5.3. Gestion de l’Expiration
- Expiration automatique : Sessions expirées après 7 jours
- Rafraîchissement : Sessions actives rafraîchies quotidiennement
- Logout explicite : Suppression immédiate de la session
- Concurrent sessions : Support multi-device par utilisateur
6. Gestion des Mots de Passe (CODE)
6.1. Hash des Mots de Passe
Better Auth utilise automatiquement :
- Algorithmes de hash modernes (bcrypt, argon2)
- Salt unique par mot de passe
- Facteur de travail configurable
6.2. Configuration Password
export function createAuth(env: any) { return betterAuth({ ...withCloudflare( { d1: { db }, kv: env.AUTH_KV }, { account: { password: { min: 8, max: 32, requireNumbers: true, requireSpecialChars: true } } } ) });}6.3. Politique de Mots de Passe
| Règle | Valeur | Description |
|---|---|---|
| Longueur min | 8 caractères | Sécurité minimale |
| Longueur max | 32 caractères | Limite stockage |
| Nombres requis | Oui | Complexité |
| Caractères spéciaux | Oui | Complexité |
| Rotation | Non requise | À évaluer |
7. Audit et Logging (CODE)
7.1. Configuration Logging
export function createAuth(env: any) { return betterAuth({ ...withCloudflare( { d1: { db }, kv: env.AUTH_KV }, { advanced: { logger: { level: env.ENVIRONMENT === 'prod' ? 'error' : 'debug', verbose: env.ENVIRONMENT === 'dev' } } } ) });}7.2. Événements à Logger
- Login réussi : User ID, IP, timestamp
- Login échoué : Email, IP, raison, timestamp
- Logout : User ID, timestamp
- Session créée : User ID, session ID, timestamp
- Session expirée : Session ID, timestamp
- Tentative brute force : IP, nombre tentatives, timestamp
7.3. Stockage des Logs
// Optionnel : Stocker les logs dans D1 ou Cloudflare Analytics// Pour l'instant, utiliser Cloudflare Workers Logs8. Rate Limiting (CODE)
8.1. Configuration Rate Limiting
export function createAuth(env: any) { return betterAuth({ ...withCloudflare( { d1: { db }, kv: env.AUTH_KV }, { advanced: { rateLimit: { enabled: true, window: 60, // 60 secondes max: 5 // 5 requêtes max } } } ) });}8.2. Politique Rate Limiting
| Endpoint | Window | Max | Description |
|---|---|---|---|
/api/auth/sign-in |
60s | 5 | Tentatives login |
/api/auth/sign-up |
60s | 3 | Tentatives inscription |
/api/auth/forgot-password |
60s | 3 | Reset password |
8.3. Response Rate Limiting
{ "error": "Too many requests", "message": "Rate limit exceeded. Please try again later.", "retryAfter": 45}9. Sécurité Environment (CODE)
9.1. Variables d’Environnement (.env.example)
# Better AuthBETTER_AUTH_SECRET=your-32-char-secret-hereBETTER_AUTH_URL=http://localhost:4321
# CloudflareCLOUDFLARE_ACCOUNT_ID=your-account-idCLOUDFLARE_API_TOKEN=your-api-token
# DatabaseAUTH_DB_ID=your-d1-database-idAUTH_KV_ID=your-kv-namespace-id
# EnvironmentENVIRONMENT=dev9.2. Validation Environment
export function validateEnv(env: any): boolean { const required = [ 'BETTER_AUTH_SECRET', 'CLOUDFLARE_ACCOUNT_ID', 'AUTH_DB_ID', 'AUTH_KV_ID' ];
for (const key of required) { if (!env[key]) { throw new Error(`Missing required environment variable: ${key}`); } }
if (env.BETTER_AUTH_SECRET.length < 32) { throw new Error('BETTER_AUTH_SECRET must be at least 32 characters'); }
return true;}10. Contrats de Sécurité (SPEC)
10.1. Niveau de Sécurité
| Composant | Niveau | Description |
|---|---|---|
| Secrets | Critique | Génération, stockage, rotation |
| Cookies | Élevé | HttpOnly, Secure, SameSite |
| CSRF | Élevé | Protection automatique |
| Sessions | Moyen | Expiration, rafraîchissement |
| Passwords | Élevé | Hash, complexité |
| Rate Limiting | Moyen | Protection brute force |
10.2. Critères de Validation
- Secrets ≥ 32 caractères
- Cookies HttpOnly + Secure (prod)
- CSRF protection activée
- Sessions expirent après 7 jours
- Passwords hashés correctement
- Rate limiting configuré
- Logging activé
- Variables d’environnement validées
11. Tests de Sécurité (TEST)
11.1. Tests Secrets
- Secret généré aléatoirement
- Secret non commité dans git
- Secret injecté via wrangler
- Rotation fonctionnelle
11.2. Tests Cookies
- Cookie HttpOnly accessible
- Cookie Secure en prod uniquement
- Cookie SameSite=lax
- Cookie expiré après 7 jours
11.3. Tests CSRF
- Requête sans Origin rejetée
- Requête avec Origin invalide rejetée
- Requête avec Origin valide acceptée
11.4. Tests Rate Limiting
- 5 requêtes login acceptées
- 6ème requête rejetée
- Retry-after header présent
12. Documentation Utilisateur
12.1. Génération Secrets
# Générer un secret sécurisénode -e "console.log(require('crypto').randomBytes(32).toString('hex'))"12.2. Injection Secrets
# Injecter secret en prodwrangler secret put BETTER_AUTH_SECRET12.3. Vérification Sécurité
# Vérifier que les secrets ne sont pas commitésgit grep BETTER_AUTH_SECRET
# Vérifier la configurationwrangler secret list13. Historique des Modifications
| Date | Version | Description | Auteur |
|---|---|---|---|
| 2026-09-27 | 1.0 | Création initiale DAT Politique Sécurité | Team (Agent) |