Skip to content

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

  1. Spécifier la configuration Better Auth Cloudflare avec D1 + KV
  2. Définir le schéma de base de données et les migrations
  3. Spécifier les endpoints d’authentification
  4. Définir la configuration des cookies et sessions
  5. Spécifier l’intégration avec le middleware Astro

1.2. Contraintes

  • Utiliser wrangler.jsonc au lieu de wrangler.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 : Utilisateurs
  • session : Sessions utilisateurs
  • account : 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 Auth
BETTER_AUTH_SECRET=<random-32-char-secret>
BETTER_AUTH_URL=http://localhost:4321
# Cloudflare
CLOUDFLARE_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>
# Environment
ENVIRONMENT=dev

4.2. Injection Secrets1/2

Script d’injection : ./scripts/inject_secret_to_cloudflare.sh

Terminal window
# Injection secrets pour l'app web
./scripts/inject_secret_to_cloudflare.sh --env=dev --service=web

4.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

apps/web/src/middleware.ts
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 :

Terminal window
./scripts/migrate-d1.sh --env=dev --action=generate

Application migrations :

Terminal window
./scripts/migrate-d1.sh --env=dev --action=apply
./scripts/migrate-d1.sh --env=prod --action=apply

6.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 Drizzle

6.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 :

Terminal window
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Injection secrets :

Terminal window
./scripts/inject_secret_to_cloudflare.sh --env=dev --service=web

8.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 :

  1. Première requête : Lecture D1 + écriture KV
  2. Requêtes suivantes : Lecture KV uniquement
  3. Expiration cache : 5 minutes
  4. 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)
Switch to normal mode

Contents