feat(auth): add user invitation flow with account setup

- add `createAccountSetup`, `verifyAccountSetupToken`, `deleteAccountSetupToken` to verifications core
- add `completeAccountSetup` function to auth core for password creation on invite
- add `InvitationEmail` template for sending invite links
- add `SetupAccountPage` client page for invited users to set their password
- add `UserCreateModal` admin component to invite new users
- wire invitation action and API endpoint in auth feature
- update admin `UsersPage` to include user creation modal
- update auth and admin README docs
This commit is contained in:
2026-04-25 09:03:15 -04:00
parent 96c8cf1e97
commit abd9d651dc
16 changed files with 681 additions and 21 deletions
+45 -2
View File
@@ -11,7 +11,7 @@ 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
├── 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
@@ -29,13 +29,15 @@ src/features/auth/
│ ├── 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
── EmailChangeNotifyEmail.js
└── InvitationEmail.js
```
---
@@ -66,6 +68,7 @@ export { default } from '@zen/core/features/auth/server';
| `/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 |
---
@@ -144,6 +147,19 @@ Vérifie le token de confirmation et marque l'adresse comme vérifiée.
---
### `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.
@@ -165,6 +181,7 @@ Les routes sont enregistrées automatiquement sous le préfixe `/zen/api`. L'aut
| 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 |
@@ -200,6 +217,32 @@ Les routes sont enregistrées automatiquement sous le préfixe `/zen/api`. L'aut
---
## 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é.