SPEC — Better Auth Cloudflare Configuration
SPEC — Better Auth Cloudflare Configuration
Spécification technique détaillée
Cycle : DOC → SPEC → CODE → TEST → INTÉG
Composant : Better Auth Cloudflare Integration
Fichier :docs/L3_Backend/cloudflare/better-auth/SPEC-Better-Auth-Cloudflare.md
Statut : SPEC
1. Périmètre et Objectifs
1.1. Objectifs
- Spécifier la configuration Better Auth Cloudflare avec D1 + KV
- Définir le schéma de base de données et les migrations
- Spécifier les endpoints d’authentification
- Définir la configuration des cookies et sessions
- Spécifier l’intégration avec le middleware Astro
1.2. Contraintes
- Utiliser
wrangler.jsoncau lieu dewrangler.toml - Activer l’observabilité dans la configuration
- Utiliser les scripts automatisés pour création ressources
- Utiliser les ressources existantes pour dev/prod
- Suivre les best practices Cloudflare
2. Spécification Better Auth Cloudflare
2.1. Configuration withCloudflare1/2
Interface TypeScript :
interface BetterAuthCloudflareConfig { d1?: { db: D1Database; options?: { usePlural?: boolean }; }; kv?: KVNamespace; autoDetectIpAddress?: boolean;}2.1. Configuration withCloudflare2/2
Configuration requise :
import { betterAuth } from "better-auth";import { withCloudflare } from "better-auth-cloudflare";import { drizzleAdapter } from "@better-auth/drizzle-adapter";import { drizzle } from "drizzle-orm/d1";
export function createAuth(env: any) { const db = drizzle(env.AUTH_DB, { schema });
return betterAuth({ ...withCloudflare( { d1: { db, options: { usePlural: true } }, kv: env.AUTH_KV, autoDetectIpAddress: true }, { database: drizzleAdapter(db, { provider: "sqlite" }), // ... autres options } ) });}2.2. Schéma D1 (Géré par Better Auth)1/3
Tables générées automatiquement :
user: Utilisateurssession: Sessions utilisateursaccount: Comptes OAuth (optionnel)verification: Vérifications email/password
2.2. Schéma D1 (Géré par Better Auth)2/3
Colonnes user :
{ id: string; // UUID email: string; // Unique, not null emailVerified: boolean; // Default false name: string; // Optionnel image: string; // Optionnel (URL avatar) createdAt: number; // Timestamp updatedAt: number; // Timestamp}2.2. Schéma D1 (Géré par Better Auth)3/3
Colonnes session :
{ id: string; // UUID userId: string; // Foreign key user.id expiresAt: number; // Timestamp expiration token: string; // Unique token ipAddress: string; // Optionnel userAgent: string; // Optionnel createdAt: number; // Timestamp updatedAt: number; // Timestamp}2.3. Endpoints d’Authentification1/3
Endpoints Better Auth (générés automatiquement) :
| Endpoint | Méthode | Description | Auth requise |
|---|---|---|---|
/api/auth/sign-in |
POST | Connexion utilisateur | Non |
/api/auth/sign-up |
POST | Inscription utilisateur | Non |
/api/auth/sign-out |
POST | Déconnexion utilisateur | Oui |
/api/auth/session |
GET | Récupérer session courante | Non |
/api/auth/user |
GET | Récupérer utilisateur courant | Oui |
2.3. Endpoints d’Authentification2/3
Payload sign-in :
{ email: string; password: string;}Response sign-in :
2.3. Endpoints d’Authentification3/3
{ user: { id: string; email: string; name: string | null; image: string | null; }; session: { token: string; expiresAt: number; };}2.4. Configuration Cookies et Sessions1/2
Attributs cookies :
{ prefix: "amn-auth"; httpOnly: true; secure: ENVIRONMENT === 'prod'; sameSite: "lax"; maxAge: 604800; // 7 days}2.4. Configuration Cookies et Sessions2/2
Politique de session :
{ expiresIn: 60 * 60 * 24 * 7; // 7 days updateAge: 60 * 60 * 24; // 1 day cookieCache: { maxAge: 5 * 60; // 5 minutes enabled: true }}3. Spécification Configuration wrangler.jsonc
3.1. Structure wrangler.jsonc1/2
3.1. Structure wrangler.jsonc2/2
{ "$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 } },
"d1_databases": [ { "binding": "AUTH_DB", "database_name": "amn-auth-db", "database_id": "<existing-d1-id>", "migrations_dir": "drizzle" } ],
"kv_namespaces": [ { "binding": "AUTH_KV", "id": "<existing-kv-id>" } ],
"env": { "dev": { "name": "amn-dev", "observability": { "enabled": true, "logs": { "head_sampling_rate": 1 }, "traces": { "enabled": true, "head_sampling_rate": 0.01 } }, "d1_databases": [ { "binding": "AUTH_DB", "database_name": "amn-auth-db", "database_id": "<existing-d1-id>", "migrations_dir": "drizzle" } ], "kv_namespaces": [ { "binding": "AUTH_KV", "id": "<existing-kv-id>" } ] }, "prod": { "name": "amn-prod", "observability": { "enabled": true, "logs": { "head_sampling_rate": 1 }, "traces": { "enabled": true, "head_sampling_rate": 0.01 } }, "d1_databases": [ { "binding": "AUTH_DB", "database_name": "amn-auth-db", "database_id": "<existing-d1-id>", "migrations_dir": "drizzle" } ], "kv_namespaces": [ { "binding": "AUTH_KV", "id": "<existing-kv-id>" } ] } }}3.2. Règles de Configuration
Règle 1 : Toujours utiliser wrangler.jsonc au lieu de wrangler.toml
Règle 2 : Toujours activer l’observabilité
Règle 3 : Toujours utiliser les ressources existantes pour dev/prod
Règle 4 : Toujours utiliser le script create-cloudflare-resources.sh pour création ressources
Règle 5 : Toujours utiliser le script migrate-d1.sh pour migrations D1
4. Spécification Variables d’Environnement
4.1. Variables Requises
# Better AuthBETTER_AUTH_SECRET=<random-32-char-secret>BETTER_AUTH_URL=http://localhost:4321
# CloudflareCLOUDFLARE_ACCOUNT_ID=<your-account-id>CLOUDFLARE_API_TOKEN=<your-api-token>
# Resources (utilisées pour création/migration uniquement)AUTH_DB_ID=<existing-d1-id>AUTH_KV_ID=<existing-kv-id>
# EnvironmentENVIRONMENT=dev4.2. Injection Secrets1/2
Script d’injection : ./scripts/inject_secret_to_cloudflare.sh
# Injection secrets pour l'app web./scripts/inject_secret_to_cloudflare.sh --env=dev --service=web4.2. Injection Secrets2/2
Mapping des secrets :
{ BETTER_AUTH_SECRET: string; BETTER_AUTH_URL: string; CLOUDFLARE_ACCOUNT_ID: string; CLOUDFLARE_API_TOKEN: string;}5. Spécification Intégration Middleware Astro
5.1. Interface Env
interface Env { AUTH_DB: D1Database; AUTH_KV: KVNamespace; ENVIRONMENT: 'dev' | 'prod';}5.2. Middleware avec Better Auth
import { defineMiddleware } from 'astro:middleware';import { createAuth } from './auth/index';
export const onRequest = defineMiddleware(async (context, next) => { const { pathname } = context.url;
// Pour les routes de documentation privées if (pathname.startsWith('/docs/') || pathname.startsWith('/gettingStarted/')) { const auth = createAuth(context.locals.runtime.env); const session = await auth.api.getSession({ headers: context.request.headers });
if (!session) { return context.redirect(`/login?redirectTo=${encodeURIComponent(pathname)}`); }
context.locals.user = session.user; }
return next();});5.3. Interface Locals
declare namespace App { interface Locals { user?: { id: string; email: string; name: string | null; image: string | null; } | null; }}6. Spécification Migrations
6.1. Workflow Migrations
Génération schéma :
./scripts/migrate-d1.sh --env=dev --action=generateApplication migrations :
./scripts/migrate-d1.sh --env=dev --action=apply./scripts/migrate-d1.sh --env=prod --action=apply6.2. Fichiers Générés
Structure drizzle/ :
drizzle/├── schema.ts # Schéma Drizzle (généré par Better Auth)├── migrations/ # Fichiers SQL de migration│ ├── 0001_initial.sql│ └── ...└── config.ts # Configuration Drizzle6.3. Validation Migrations
Critères de validation :
- Tables créées dans D1
- Index créés correctement
- Foreign keys configurés
- Données de test insérées (si applicable)
7. Spécification Tests
7.1. Tests Unitaires
Test configuration Better Auth :
describe('Better Auth Configuration', () => { it('should create auth instance with D1', () => { const env = { AUTH_DB: mockD1Database, AUTH_KV: mockKVNamespace, ENVIRONMENT: 'dev' }; const auth = createAuth(env); expect(auth).toBeDefined(); });});7.2. Tests d’Intégration
Test flux sign-in :
describe('Sign-in Flow', () => { it('should sign in user with valid credentials', async () => { const response = await fetch('/api/auth/sign-in', { method: 'POST', body: JSON.stringify({ email: 'test@example.com', password: 'password123' }) }); expect(response.status).toBe(200); const data = await response.json(); expect(data.user).toBeDefined(); expect(data.session).toBeDefined(); });});7.3. Tests Middleware
Test protection routes privées :
describe('Middleware Protection', () => { it('should redirect to login for private docs without session', async () => { const response = await fetch('/docs/private-doc'); expect(response.status).toBe(302); expect(response.headers.get('location')).toContain('/login'); });});8. Spécification Sécurité
8.1. Gestion Secrets
Génération secret :
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"Injection secrets :
./scripts/inject_secret_to_cloudflare.sh --env=dev --service=web8.2. Configuration Cookies1/2
Développement :
{ httpOnly: true, secure: false, // HTTP local sameSite: "lax"}8.2. Configuration Cookies2/2
Production :
{ httpOnly: true, secure: true, // HTTPS uniquement sameSite: "lax"}8.3. Protection CSRF
Better Auth inclut automatiquement :
- Validation Origin/Referer headers
- Protection contre CSRF sur les requêtes state-changing
- Tokens CSRF automatiques
9. Spécification Performance
9.1. Cache KV
Flux cache :
- Première requête : Lecture D1 + écriture KV
- Requêtes suivantes : Lecture KV uniquement
- Expiration cache : 5 minutes
- Fallback : D1 en cas de miss KV
9.2. Observabilité
Logs :
- Sampling rate : 100% (head_sampling_rate: 1)
- Logs : Toutes les requêtes authentification
- Errors : Erreurs d’authentification
Traces :
- Sampling rate : 1% (head_sampling_rate: 0.01)
- Traces : Requêtes lentes et erreurs
- Performance : Temps de réponse D1/KV
10. Spécification Migration depuis Auth-Handler
10.1. Analyse Impact
Endpoints à migrer :
/api/auth/login→/api/auth/sign-in/api/auth/logout→/api/auth/sign-out/api/auth/verify→/api/auth/session
Sessions existantes :
- Option 1 : Migration automatique (script)
- Option 2 : Reset sessions (reconnexion requise)
- Recommandation : Option 2 (plus simple)
10.2. Plan Migration
Phase 1 : Installer Better Auth sans désactiver auth-handler Phase 2 : Configurer Better Auth en parallèle Phase 3 : Tester endpoints Better Auth Phase 4 : Migrer frontend vers nouveaux endpoints Phase 5 : Désactiver auth-handler Phase 6 : Nettoyer code auth-handler
11. Critères de Validation
11.1. Validation Technique
- wrangler.jsonc configuré avec observabilité
- D1 database liée et accessible
- KV namespace liée et accessible
- Better Auth configuré correctement
- Migrations appliquées avec succès
- Secrets injectés via script
11.2. Validation Fonctionnelle
- Sign-in fonctionne avec credentials valides
- Sign-up fonctionne (si activé)
- Sign-out fonctionne correctement
- Session persiste après refresh
- Session expire après 7 jours
- Middleware protège les routes privées
11.3. Validation Sécurité
- Secrets non commités dans git
- Cookies HttpOnly + Secure (prod)
- CSRF protection active
- Rate limiting configuré
- Observabilité activée
12. Historique des Modifications
| Date | Version | Description | Auteur |
|---|---|---|---|
| 2026-09-27 | 1.0 | Création initiale SPEC Better Auth Cloudflare | Team (Agent) |