Dernière mise à jour : 2026-05-04
OffFeed est une application auto-hébergée à administrateur unique. La surface d'attaque est donc réduite : un seul compte, pas d'inscription, pas de données utilisateurs tiers.
Navigateur Serveur
│ │
│── POST /api/auth/pre-login ────▶│ bcrypt.compare() + rate limit
│◀── { preToken, requires2FA } ──│ preToken = HMAC-SHA256 (TTL 3 min)
│ │
│── signIn({ preToken, totp }) ──▶│ verifyPreToken() + verifyTOTP()
│◀── session JWT ────────────────│ httpOnly cookie, 8h
Le mot de passe n'est jamais transmis à NextAuth — uniquement le preToken HMAC.
| Mécanisme | Détail |
|---|---|
| Hachage | bcrypt cost 12 — ~400 ms par tentative |
| Rate limiting | 5 essais / 15 min par IP, puis 30 min de blocage |
| Timing-safe | crypto.timingSafeEqual sur tous les secrets ; dummy hash si aucun mot de passe en DB |
| preToken | HMAC-SHA256(timestamp.nonce, NEXTAUTH_SECRET), signé à usage unique, TTL 3 min |
| Session | JWT 8h, sliding refresh 1h, cookie httpOnly + sameSite=lax + secure (prod) |
| Redirect | Callback URL limité au même origin — protection open redirect |
La 2FA TOTP est obligatoire : impossible d'accéder à l'administration sans l'avoir configurée.
- Bibliothèque :
otplib— TOTP RFC 6238 - Période : 30 secondes, fenêtre de tolérance : ±1 période
- Secret stocké en DB (SQLite) — visible uniquement côté serveur
- 8 codes générés à l'activation, affichés une seule fois
- Format :
XXXXX-XXXXX-XXXXX(15 chars alphanumériques) - Stockage : hash SHA-256 en DB — les codes en clair ne sont jamais persistés
- Usage unique : chaque code est consumé après utilisation
- Utiliser un code de secours désactive la 2FA et force la reconfiguration
- Rate limit strict : 5 tentatives / heure, puis blocage 24h
Le changement de mot de passe requiert un code TOTP valide — aucun autre canal.
Règles de complexité :
- Minimum 12 caractères, maximum 200
- Au moins 3 classes parmi : minuscules, majuscules, chiffres, symboles
La page /admin/setup permet de créer le mot de passe initial uniquement si aucun hash n'existe en DB. Elle devient automatiquement inaccessible après la première utilisation (HTTP 403).
Le middleware intercepte toutes les mutations POST / PUT / PATCH / DELETE sur /api/* (hors /api/auth/* géré par NextAuth) et vérifie que l'Origin ou le Referer correspond au même origin.
Les requêtes sans header Origin/Referer sur une méthode mutante sont rejetées (HTTP 403).
| En-tête | Valeur |
|---|---|
X-Frame-Options |
DENY |
X-Content-Type-Options |
nosniff |
Referrer-Policy |
strict-origin-when-cross-origin |
Permissions-Policy |
camera=(), microphone=(), geolocation=() |
Content-Security-Policy |
default-src 'self' + img CDN Instagram |
Strict-Transport-Security |
max-age=63072000; includeSubDomains; preload (prod) |
X-Robots-Tag |
noindex, nofollow sur /admin/* |
- Types autorisés :
image/jpeg,image/png,image/webp,image/gif - Taille max : 20 MB
- L'extension est dérivée du MIME type — jamais du nom de fichier fourni par l'utilisateur
- Nom de fichier : UUID aléatoire — aucune information utilisateur
- Stockage dans
/public/uploads/(servi statiquement)
| Endpoint | Validation |
|---|---|
GET /api/posts?tag= |
Regex [\p{L}\p{N}_-]{1,64} — rejeté sinon |
GET /api/posts?limit= |
Borné entre 1 et 100 |
POST /api/auth/totp/recover |
Format XXXXX-XXXXX-XXXXX vérifié avant tout accès DB |
| Mots de passe | 12–200 chars, 3 classes minimum |
DATABASE_URL=file:./dev.db
NEXTAUTH_URL=https://votre-domaine.com
NEXTAUTH_SECRET=<minimum 32 caractères aléatoires>Générer un secret fort :
openssl rand -base64 32- Chiffrement at-rest des credentials Instagram : les tokens IG sont stockés en clair en DB. Protégez l'accès fichier à
dev.db. - Audit log : les connexions et actions admin ne sont pas journalisées.
- 2FA WebAuthn / Passkeys : uniquement TOTP pour l'instant.
-
NEXTAUTH_SECRET≥ 32 chars aléatoires (openssl rand -base64 32) -
NEXTAUTH_URL= URL HTTPS exacte de production -
NODE_ENV=production(active HSTS, cookiesSecure, préfixes__Secure-/__Host-) - Accès fichier
*.dbrestreint (permissions Unix 600) - Reverse proxy (nginx/Caddy) avec TLS — ne pas exposer Next.js directement
- Sauvegardes régulières de
dev.db - Codes de secours 2FA imprimés ou dans un gestionnaire de mots de passe hors ligne