eptm_dashboard/data/docs/07-auth.md

71 lines
2.3 KiB
Markdown

# Authentification & rôles
## Login
Page : `/login`
L'identifiant + mot de passe sont vérifiés contre `data/auth.yaml` (mot de passe haché avec **bcrypt**).
Format `auth.yaml` :
```yaml
credentials:
usernames:
prof.demo:
password: "$2b$12$..."
name: "Prof Demo"
role: "admin" # ou "user"
avatar_url: "/avatars/prof_demo.png"
totp_secret: "ABCD1234..." # rempli automatiquement à la 1ère 2FA
```
## 2FA TOTP (obligatoire)
À la **première connexion** d'un nouvel utilisateur :
1. Login + mot de passe corrects
2. L'app génère un secret TOTP et affiche un **QR code**
3. L'utilisateur scanne avec Google Authenticator / Authy / 1Password / etc.
4. Il saisit le code à 6 chiffres pour confirmer
5. Le secret est sauvé dans `auth.yaml`
Aux connexions suivantes :
1. Login + mot de passe → demande directe du code TOTP
2. Code à 6 chiffres → connexion finalisée
Le code est valide ±30s (paramètre `valid_window=1` de `pyotp`) pour tolérer la dérive d'horloge.
## Session persistante
L'authentification est stockée dans le **`localStorage` du navigateur** (champs `username`, `name`, `role`, `photo_url`). La session survit aux rechargements de page et aux redémarrages du conteneur.
À chaque page protégée, `AuthState.check_auth` re-vérifie que l'utilisateur existe toujours dans `auth.yaml` ; sinon, redirection forcée vers `/login`.
## Rôles
| Page | user | admin |
|-------------------|------|-------|
| `/accueil` | ✅ | ✅ |
| `/fiche` | ✅ | ✅ |
| `/classe` | ✅ | ✅ |
| `/doc` | ✅ | ✅ |
| `/escada` | ❌ | ✅ |
| `/cron` | ❌ | ✅ |
| `/logs` | ❌ | ✅ |
| `/users` | ❌ | ✅ |
| `/params` | ❌ | ✅ |
## Gestion des utilisateurs
Page `/users` (admin) :
- Créer / supprimer des utilisateurs
- Changer le rôle
- Réinitialiser le 2FA (efface `totp_secret` → forcera une nouvelle config au prochain login)
- Définir / changer un avatar
## Logout
Bouton "Déconnexion" en bas de la sidebar. Vide le `localStorage` et redirige vers `/login`.
## Stockage des avatars
Les fichiers sont sous `assets/avatars/`. Le chemin est référencé dans `auth.yaml` via `avatar_url`. Si `avatar_url` est vide, l'app affiche les initiales de `name`.