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