# 🔒 Guide Authentification & sécurité ObsiGate embarque un système d'authentification optionnel **JWT + Argon2id**, un contrôle d'accès **par vault**, du MFA (TOTP, WebAuthn, codes de secours) et des mécanismes de durcissement. Ce guide couvre l'activation, la gestion des comptes et les bonnes pratiques. > **Public :** administrateurs · **Voir aussi :** > [`features/api-mcp-tokens-107.md`](../features/api-mcp-tokens-107.md) · > [API REST](./API_REST.md) · [MCP](./MCP.md) · [Déploiement Docker](./DEPLOIEMENT_DOCKER.md) --- ## 1. Vue d'ensemble - **Désactivée par défaut** (`OBSIGATE_AUTH_ENABLED=false`) — compatible avec toutes les installations existantes. - Quand elle est activée, l'écran de connexion s'affiche et chaque endpoint vérifie l'utilisateur et ses permissions. - Les données d'auth (`users.json`, `secret.key`, `api_tokens.json`) vivent dans `/app/data` — **montez ce dossier en volume** pour les persister. --- ## 2. Activer l'authentification ### 2.1 Fichier `.env` ```bash cp .env.example .env ``` ```bash OBSIGATE_AUTH_ENABLED=true OBSIGATE_ADMIN_USER=admin OBSIGATE_ADMIN_PASSWORD=votre_mot_de_passe # vide = auto-généré (voir logs) # OBSIGATE_SECURE_COOKIES=false # true si derrière HTTPS ``` ### 2.2 `docker-compose.yml` ```yaml env_file: - .env ``` > **Ne mettez jamais de mot de passe dans `docker-compose.yml` !** Utilisez > toujours `.env` (non committé). ### 2.3 Premier démarrage Si aucun utilisateur n'existe, ObsiGate crée un compte admin et affiche le mot de passe **une seule fois dans les logs** : ```bash docker compose logs obsigate | grep -A4 "FIRST" ``` ``` ============================================================ FIRST STARTUP — Admin account created automatically Username : admin Password : xK9mQ3pLr7wN2jT5 CHANGE THIS PASSWORD on first login! ============================================================ ``` Changez-le immédiatement (menu profil → *Changer le mot de passe*). --- ## 3. Gestion des utilisateurs ### 3.1 Interface d'administration Un compte **admin** voit une icône 🛡️ dans le header. Le panneau permet de : - lister tous les utilisateurs ; - créer / modifier / supprimer des comptes ; - assigner les vaults accessibles par utilisateur ; - activer / désactiver des comptes. ### 3.2 Ligne de commande ```bash # Créer un utilisateur docker exec obsigate python backend/create_admin.py create alice MotDePasse --role user --vaults Recettes IT # Créer un admin avec accès total docker exec obsigate python backend/create_admin.py create bob SecretPass --role admin --vaults "*" # Lister docker exec obsigate python backend/create_admin.py list # Supprimer docker exec obsigate python backend/create_admin.py delete alice ``` ### 3.3 Contrôle d'accès par vault | Valeur `vaults` | Accès | |---|---| | `["*"]` | Toutes les vaults (y compris futures) — défaut admin | | `["Recettes", "IT"]` | Uniquement ces vaults | | `[]` | Aucun accès | Les permissions sont revérifiées à chaque requête (et à chaque connexion WebSocket de collaboration). --- ## 4. MFA (authentification multifacteur) ObsiGate propose trois secondes facteurs, configurables par l'utilisateur. ### 4.1 TOTP (application d'authentification) 1. Menu profil → **Sécurité** → *Configurer TOTP* (`POST /api/auth/mfa/totp/setup`). 2. Scannez le QR code avec Google Authenticator, Authy, etc. 3. Validez le code (`POST /api/auth/mfa/totp/enable`). 4. Désactivation : `POST /api/auth/mfa/totp/disable` (mot de passe requis). ### 4.2 Clés de sécurité & biométrie (WebAuthn) - Enregistrement : `POST /api/auth/mfa/webauthn/register/options` puis `POST /api/auth/mfa/webauthn/register`. - Connexion : `POST /api/auth/mfa/webauthn/options` puis `/verify`. - Gestion des clés : `GET /api/auth/mfa/webauthn/credentials`, `POST /api/auth/mfa/webauthn/credentials/remove`. > Le *relying party* (domaine) est **dérivé de la requête** (hôte exact, port > inclus) ; derrière un reverse proxy, activez `OBSIGATE_TRUST_PROXY=true` pour > que `X-Forwarded-Host/Proto` soient pris en compte. ### 4.3 Codes de secours À l'activation du MFA, des **codes de récupération** sont générés. Utilisez-en un via `POST /api/auth/mfa/recovery` si vous perdez votre second facteur. Conservez- les hors ligne. ### 4.4 Statut `GET /api/auth/mfa/status` indique les facteurs actifs pour le compte courant. --- ## 5. Clés API & MCP Pour les scripts et les clients externes, créez une **clé API longue durée** (1 j, 1 mois, 6 mois, 1 an, sans fin) depuis Configurations → 🔑 **Clés API & MCP**. Une seule clé authentifie l'API REST **et** le serveur MCP. - Le secret n'est **affiché qu'une fois** (pattern GitHub) et n'est jamais persisté. - La révocation est **immédiate** des deux côtés. - Une colonne « dernière utilisation » (throttlée) aide à repérer les clés dormantes. Détails : [API REST §2.2](./API_REST.md#22-clés-api-longue-durée-recommandé-pour-scripts--mcp) et [`features/api-mcp-tokens-107.md`](../features/api-mcp-tokens-107.md). --- ## 6. Mécanismes de durcissement | Mécanisme | Détail | |---|---| | **Path traversal** | Chaque endpoint fichier valide que le chemin résolu reste dans la vault | | **Rate limiting** | 10 tentatives de login max par IP / 15 min + lockout par compte | | **Rate limiting MFA** | Appliqué aux endpoints TOTP/WebAuthn/recovery | | **Audit log** | Écritures, suppressions, config dans `data/audit.log` (JSON lines, rotation 10 Mo) | | **Backup automatique** | Avant chaque modification/suppression dans `.obsigate-backup/` | | **Redaction** | Masquage des JWT, clés API, tokens dans les aperçus et retours d'outils | | **CSP** | `object-src`, `base-uri`, `form-action`, `frame-ancestors` restreints | | **Cookie HttpOnly** | Jeton retiré de `sessionStorage`, porté par cookie HTTP-only | | **Utilisateur non-root** | Conteneur sous `obsigate` (UID 1000) | | **Volumes read-only** | Vaults montées `:ro` par défaut | | **Atomic writes** | `users.json`, `shares.json`, `webhooks.json` écrits en tmp+replace | | **Symlinks ignorés** | L'index n'indexe pas les liens symboliques | ### Politique de mot de passe Une politique minimale est validée à la création d'un compte. Choisissez des mots de passe longs et uniques ; activez le MFA pour les comptes admin. --- ## 7. Variables d'environnement | Variable | Description | Défaut | |---|---|---| | `OBSIGATE_AUTH_ENABLED` | Activer l'authentification | `false` | | `OBSIGATE_ADMIN_USER` | Nom de l'admin auto-créé | `admin` | | `OBSIGATE_ADMIN_PASSWORD` | Mot de passe admin (vide = auto-généré) | *(auto)* | | `OBSIGATE_SECURE_COOKIES` | Cookie `Secure` (HTTPS uniquement) | `false` | | `OBSIGATE_ACCESS_TOKEN_TTL` | Durée de vie du token d'accès (s) | `3600` | | `OBSIGATE_REFRESH_TOKEN_TTL` | Durée de vie du refresh token (s) | `2592000` | | `OBSIGATE_LOGIN_MAX_ATTEMPTS` | Tentatives de login max par IP | `10` | | `OBSIGATE_ACCOUNT_MAX_ATTEMPTS` | Tentatives de login max par compte | `10` | | `OBSIGATE_LOGIN_WINDOW_SECONDS` | Fenêtre de rate limiting (s) | `900` | | `OBSIGATE_TRUST_PROXY` | Faire confiance à `X-Forwarded-For` / `Host` | `false` | Toutes ces variables sont documentées dans `.env.example`. --- ## 8. Déploiement sécurisé (checklist) - [ ] `OBSIGATE_AUTH_ENABLED=true` sur toute instance exposée. - [ ] Mot de passe admin fort, changé après le premier démarrage. - [ ] MFA activé pour les comptes admin. - [ ] HTTPS via reverse proxy + `OBSIGATE_SECURE_COOKIES=true`. - [ ] `OBSIGATE_TRUST_PROXY=true` **uniquement** derrière un proxy de confiance. - [ ] Volume `./data:/app/data` monté et **sauvegardé**. - [ ] Vaults montées en `:ro` (lecture seule) sauf besoin d'écriture. - [ ] Clés API révoquées dès qu'elles ne servent plus. - [ ] Accès réseau restreint (VPN / pare-feu) si possible. --- ## 9. Dépannage | Symptôme | Piste | |---|---| | Login bloqué `429` | Rate limit : attendre la fenêtre (`OBSIGATE_LOGIN_WINDOW_SECONDS`) | | WebAuthn refuse l'enregistrement | Domaine/port non dérivés — activer `OBSIGATE_TRUST_PROXY` derrière un proxy | | TOTP « challenge inattendu » | Relancer la cérémonie ; les 5 derniers challenges sont acceptés | | Perte du second facteur | Utiliser un code de secours (`/api/auth/mfa/recovery`) | | Sessions perdues au redémarrage | Le volume `./data` n'est pas monté | | Clé API `401` | Clé expirée ou révoquée — en créer une nouvelle |