# Auth Ce répertoire gère l'authentification : inscription, connexion, sessions, réinitialisation de mot de passe, vérification d'adresse courriel et gestion du profil. Il expose des server actions Next.js, des routes API REST et des composants de pages prêts à l'emploi. --- ## Structure ``` src/features/auth/ ├── index.js barrel serveur ├── actions.js server actions Next.js ('use server') ├── api.js routes API REST (users, roles) ├── auth.js register, login, resetPassword, updateUser, completeAccountSetup ├── session.js createSession, validateSession, deleteSession ├── email.js tokens de vérification + envoi des e-mails ├── password.js hashPassword, verifyPassword, generateToken ├── db.js createTables, dropTables ├── storage-policies.js politiques d'accès au stockage ├── AuthPage.server.js page RSC racine (route catch-all) ├── AuthPage.client.js shell client ├── GUIDE-custom-login.md guide pour les pages personnalisées ├── components/ │ └── AuthPageHeader.js ├── pages/ │ ├── index.js re-export │ ├── LoginPage.client.js │ ├── RegisterPage.client.js │ ├── ForgotPasswordPage.client.js │ ├── ResetPasswordPage.client.js │ ├── ConfirmEmailPage.client.js │ ├── SetupAccountPage.client.js │ └── LogoutPage.client.js └── templates/ ├── VerificationEmail.js ├── PasswordResetEmail.js ├── PasswordChangedEmail.js ├── EmailChangeConfirmEmail.js ├── EmailChangeNotifyEmail.js └── InvitationEmail.js ``` --- ## Import ```js import { getSession, loginAction, logoutAction } from '@zen/core/features/auth/actions'; import { LoginPage, RegisterPage } from '@zen/core/features/auth/pages'; import { validateSession, createSession } from '@zen/core/features/auth'; ``` --- ## Pages intégrées La route catch-all `app/auth/[...auth]/page.js` suffit pour exposer toutes les pages sans configuration supplémentaire. ```js // app/auth/[...auth]/page.js export { default } from '@zen/core/features/auth/server'; ``` | Route | Page | |-------|------| | `/auth/login` | Connexion | | `/auth/register` | Inscription | | `/auth/forgot` | Mot de passe oublié | | `/auth/reset` | Réinitialisation du mot de passe | | `/auth/confirm` | Vérification de l'adresse courriel | | `/auth/setup` | Configuration du compte après invitation admin | | `/auth/logout` | Déconnexion | --- ## Server actions Toutes les actions sont dans `@zen/core/features/auth/actions`. Elles attendent un `FormData` sauf `getSession`, `setSessionCookie` et `refreshSessionCookie`. ### `getSession()` Lit le cookie de session et retourne la session courante, ou `null` si l'utilisateur n'est pas connecté. Renouvelle automatiquement le cookie si la session a été rafraîchie. ```js const session = await getSession(); if (!session?.user) redirect('/auth/login'); // session.user, session.session disponibles ``` --- ### `loginAction(formData)` Authentifie l'utilisateur et pose un cookie `HttpOnly`. Applique le rate limiting par IP et les vérifications anti-bot. ```js const result = await loginAction(formData); // { success: true, user } ou { success: false, error } ``` --- ### `registerAction(formData)` Crée un compte et envoie l'e-mail de vérification. | Champ | Description | |-------|-------------| | `email` | Adresse courriel | | `password` | Mot de passe | | `name` | Nom d'affichage | --- ### `logoutAction()` Invalide la session en base et supprime le cookie. --- ### `forgotPasswordAction(formData)` Envoie un lien de réinitialisation si un compte existe pour l'adresse fournie. La réponse ne révèle pas si le compte existe. --- ### `resetPasswordAction(formData)` Vérifie le token puis met à jour le mot de passe. | Champ | Description | |-------|-------------| | `email` | Adresse courriel | | `token` | Token reçu par e-mail | | `newPassword` | Nouveau mot de passe | --- ### `verifyEmailAction(formData)` Vérifie le token de confirmation et marque l'adresse comme vérifiée. | Champ | Description | |-------|-------------| | `email` | Adresse courriel | | `token` | Token reçu par e-mail | --- ### `setupAccountAction(formData)` Vérifie le token d'invitation, crée le compte credential et marque l'adresse comme vérifiée. Appelée depuis `/auth/setup` après qu'un admin a créé le compte sans mot de passe. | Champ | Description | |-------|-------------| | `email` | Adresse courriel | | `token` | Token reçu dans le courriel d'invitation | | `newPassword` | Mot de passe choisi | | `confirmPassword` | Confirmation du mot de passe | --- ### `setSessionCookie(token)` Valide le token contre la base avant de l'écrire dans le cookie `HttpOnly`. À utiliser après une authentification externe ou OAuth. --- ### `refreshSessionCookie(token)` Revalide le token et prolonge la durée de vie du cookie (30 jours). --- ## Routes API REST Les routes sont enregistrées automatiquement sous le préfixe `/zen/api`. L'authentification est appliquée par le routeur avant chaque handler. ### Utilisateurs | Méthode | Route | Auth | Description | |---------|-------|------|-------------| | `GET` | `/zen/api/users` | admin | Liste paginée des utilisateurs | | `POST` | `/zen/api/users` | admin | Créer un utilisateur (avec ou sans invitation) | | `GET` | `/zen/api/users/:id` | admin | Détail d'un utilisateur | | `PUT` | `/zen/api/users/:id` | admin | Modifier `name`, `role`, `email_verified` | | `PUT` | `/zen/api/users/:id/email` | admin | Changer l'adresse courriel | | `PUT` | `/zen/api/users/:id/password` | admin | Définir un mot de passe | | `POST` | `/zen/api/users/:id/send-password-reset` | admin | Envoyer un lien de réinitialisation | | `GET` | `/zen/api/users/:id/roles` | admin | Lister les rôles de l'utilisateur | | `POST` | `/zen/api/users/:id/roles` | admin | Assigner un rôle | | `DELETE` | `/zen/api/users/:id/roles/:roleId` | admin | Révoquer un rôle | ### Profil (utilisateur connecté) | Méthode | Route | Description | |---------|-------|-------------| | `PUT` | `/zen/api/users/profile` | Modifier le nom | | `POST` | `/zen/api/users/profile/email` | Initier un changement d'adresse courriel | | `GET` | `/zen/api/users/email/confirm` | Confirmer le changement d'adresse | | `POST` | `/zen/api/users/profile/password` | Changer le mot de passe | | `POST` | `/zen/api/users/profile/picture` | Téléverser une photo de profil | | `DELETE` | `/zen/api/users/profile/picture` | Supprimer la photo de profil | | `GET` | `/zen/api/users/profile/sessions` | Lister les sessions actives | | `DELETE` | `/zen/api/users/profile/sessions` | Révoquer toutes les sessions | | `DELETE` | `/zen/api/users/profile/sessions/:sessionId` | Révoquer une session | ### Rôles | Méthode | Route | Description | |---------|-------|-------------| | `GET` | `/zen/api/roles` | Lister les rôles | | `POST` | `/zen/api/roles` | Créer un rôle | | `GET` | `/zen/api/roles/:id` | Détail d'un rôle | | `PUT` | `/zen/api/roles/:id` | Modifier un rôle | | `DELETE` | `/zen/api/roles/:id` | Supprimer un rôle | --- ## Invitation par l'admin Un administrateur peut créer un utilisateur depuis `/admin/users → Nouvel utilisateur`. Deux flux selon si un mot de passe est fourni : **Avec mot de passe :** l'utilisateur est créé avec `email_verified = true` et un compte credential. Il peut se connecter immédiatement. **Sans mot de passe :** l'utilisateur est créé avec `email_verified = false` et aucun compte credential. Un token `account_setup` (48 h) est généré et un courriel d'invitation est envoyé. L'utilisateur clique sur le lien `/auth/setup?email=X&token=Y`, choisit son mot de passe, et le compte est activé (`email_verified = true`) en une seule étape — le passage par le lien vaut confirmation du courriel. ``` Admin crée l'utilisateur (sans mdp) → POST /zen/api/users → zen_auth_users créé (email_verified: false) → token account_setup enregistré dans zen_auth_verifications (48 h) → courriel InvitationEmail envoyé Utilisateur clique sur le lien /auth/setup → SetupAccountPage (setupAccountAction) → token vérifié → zen_auth_accounts créé avec mot de passe haché → email_verified = true → token supprimé → redirection vers /auth/login ``` --- ## Sécurité **Rate limiting par IP.** Les actions `register`, `login`, `forgot_password`, `reset_password` et `verify_email` sont limitées par adresse IP. Quand l'IP est inconnue (pas de proxy configuré), le rate limiting est suspendu et un avertissement opérateur est émis une seule fois. Activer avec `ZEN_TRUST_PROXY=true` derrière un reverse proxy vérifié. **Champs anti-bot.** Chaque formulaire embarque un champ honeypot (`_hp`) et un timestamp de chargement (`_t`). Une soumission trop rapide (moins de 1,5 s), trop ancienne (plus de 10 min) ou avec un honeypot rempli est rejetée. **Cookie HttpOnly.** Le token de session n'est jamais exposé à JavaScript. `setSessionCookie` et `refreshSessionCookie` valident le token en base avant d'écrire le cookie pour éviter qu'un token arbitraire soit accepté. **Erreurs opaques.** Les erreurs internes sont loguées côté serveur et remplacées par un message générique côté client. Seules les `UserFacingError` (token expiré, etc.) remontent verbatim. --- ## Base de données `db.js` expose `createTables()` et `dropTables()`, appelés par `initializeZen()`. | Table | Contenu | |-------|---------| | `zen_auth_users` | Utilisateurs (`id`, `email`, `name`, `role`, `email_verified`, `image`) | | `zen_auth_sessions` | Sessions actives avec IP et user-agent | | `zen_auth_accounts` | Comptes liés à un provider (credential, OAuth) | | `zen_auth_verifications` | Tokens de vérification d'e-mail et de réinitialisation | --- ## Pages personnalisées Pour envelopper les pages auth dans un layout existant, voir [GUIDE-custom-login.md](./GUIDE-custom-login.md). Le guide couvre le pattern serveur/client, les props de chaque composant et la protection de route.