Aller au contenu principal

Authentification et sécurité

Libre WebUI utilise des comptes locaux avec des sessions JWT. Une nouvelle installation autorise toujours l’amorçage d’un administrateur local. L’inscription publique de tous les comptes locaux ou OAuth ultérieurs est fermée par défaut.

Première configuration

Lorsque la base de données ne contient aucun utilisateur :

  1. Libre WebUI affiche le parcours de première configuration.
  2. La personne crée le premier compte local.
  3. Le rôle admin est attribué à ce compte.
  4. Toutes les inscriptions publiques ultérieures restent fermées, sauf activation explicite.

Les bases de données existantes conservent leurs utilisateurs et leurs rôles actuels.

Comptes locaux

L’inscription locale exige :

  • un nom d’utilisateur ;
  • un mot de passe de 12 caractères à 72 octets UTF-8, comportant une majuscule, une minuscule et un chiffre ;
  • une adresse e-mail facultative.

Les mots de passe sont hachés avec bcrypt avant leur stockage. Les routes de connexion et d’inscription sont soumises à une limitation de débit.

Approbation des inscriptions

L’inscription publique n’accorde pas à elle seule l’accès. Tout compte créé depuis le formulaire d’inscription publique ou par un fournisseur OAuth débute dans l’état pending et doit être approuvé par un administrateur avant de pouvoir se connecter.

L’amorçage constitue l’unique exception : le premier véritable compte d’une base de données vide est créé de façon atomique avec l’état active et le rôle admin, de sorte qu’une nouvelle installation dispose toujours d’un administrateur opérationnel. Toutes les inscriptions ultérieures attendent une vérification.

Ce que voit une personne en attente :

  • L’inscription réussit, mais ne renvoie aucun jeton de session. L’API répond 202 avec approvalRequired: true, et l’interface explique qu’un administrateur doit approuver le compte.
  • Une connexion par mot de passe avec des identifiants corrects est refusée avec 403 et le code ACCOUNT_PENDING ("Your account is waiting for administrator approval"). Une connexion OAuth redirige vers la page de connexion avec ?approval=pending.
  • L’état du compte est relu dans la base de données à chaque requête authentifiée ; une session ne peut donc jamais survivre à l’état active du compte.

Ce que voit un administrateur :

  • La gestion des utilisateurs présente une carte Approbations en attente qui répertorie les comptes concernés, avec pour chacun une action Activer le compte et une action de refus. Le refus supprime le compte ; il n’existe aucun état suspendu distinct.
  • Lorsqu’ils sont connectés, les administrateurs reçoivent des notifications dans l’application : un badge apparaît sur l’entrée Utilisateurs et une notification éphémère s’affiche lors de nouvelles inscriptions. Le résumé des approbations en attente est interrogé environ une fois par minute (GET /api/users/pending-approvals, réservé aux administrateurs).
  • L’approbation (PATCH /api/users/:id/approve, réservée aux administrateurs) enregistre l’administrateur qui l’a donnée et la date. Elle ne modifie pas le rôle : les comptes approuvés conservent le rôle user jusqu’à leur promotion par un administrateur. L’approbation prend effet à la prochaine tentative de connexion de l’utilisateur ; rien ne doit être recréé.

Une mise à niveau ne touche pas les comptes existants : seuls les comptes créés par inscription publique après la publication de la fonctionnalité débutent avec l’état en attente. Les comptes créés par un administrateur dans la gestion des utilisateurs sont immédiatement actifs.

Activer volontairement l’inscription publique

L’inscription est désactivée par défaut. Définissez la variable d’environnement suivante du serveur dorsal uniquement pendant les périodes où de nouveaux comptes locaux ou OAuth doivent être acceptés :

ENABLE_SIGNUP=true

Rétablissez-la à false après toute période d’inscription planifiée. Les utilisateurs locaux et OAuth existants peuvent toujours se connecter, et les administrateurs peuvent toujours créer des comptes dans la gestion des utilisateurs lorsque l’inscription publique est fermée.

Une base de données vide autorise toujours un administrateur local, même avec ENABLE_SIGNUP=false ; OAuth ne peut pas occuper cet emplacement d’amorçage. Pour un déploiement distant privé, placez le nom d’hôte derrière une liste d’autorisation d’identités, telle que Cloudflare Access, avant de démarrer l’application, puis créez l’administrateur initial par cette route protégée.

Rôles

RôleObjet
adminAdministration de l’instance, gestion des utilisateurs, paramètres système et exploitation fiable de Work
userParcours ordinaires de discussion, modèles, personas, documents et paramètres

L’installation, la suppression, la copie, la publication et le déchargement des modèles sont réservés aux administrateurs, car ces opérations modifient les ressources de l’hôte.

Accès à Work

Work est réservé aux administrateurs par défaut, car il permet à un modèle sélectionné d’exécuter des commandes arbitraires dans un conteneur géré. Un administrateur peut ouvrir Work à tous les utilisateurs actifs depuis l’onglet Gestion des utilisateurs des Paramètres ; ce paramètre persiste après les redémarrages et s’applique immédiatement, y compris aux sessions de terminal ouvertes. Les espaces de travail correspondant à des dossiers de l’hôte restent réservés aux administrateurs dans tous les modes, car ils montent des chemins du serveur. Considérez toute personne ayant accès à Work comme un opérateur de confiance de l’environnement d’exécution, et pas seulement comme un utilisateur de la WebUI.

L’autorisation des administrateurs est vérifiée d’après le rôle actuel dans la base de données, et pas seulement d’après le rôle mis en cache dans un JWT existant. La rétrogradation d’un administrateur révoque donc immédiatement son accès à Work. Le serveur dorsal tente ensuite d’abandonner ses exécutions actives et d’arrêter ses conteneurs et aperçus Work, tout en conservant les enregistrements des tâches et les volumes nommés. Si le nettoyage Docker échoue, l’accès reste révoqué, la modification du rôle signale cet échec et l’opérateur doit rétablir l’accès à Docker, puis relancer le nettoyage.

La suppression d’un utilisateur détruit ses données Work. Libre WebUI commence par arrêter ses conteneurs gérés et supprimer ses volumes Work, puis supprime le compte et les enregistrements de la base de données. Si Docker ne peut pas confirmer la réussite du nettoyage, la suppression du compte échoue afin qu’un administrateur puisse corriger le problème d’exécution et réessayer.

Groupes et autorisations de ressources

Les administrateurs peuvent créer des groupes et gérer leurs membres depuis l’onglet Gestion des utilisateurs des Paramètres. Les groupes sont des entités principales pour les autorisations de ressources : le propriétaire d’une discussion, d’une note, d’un document, d’une collection de connaissances, d’un dossier, d’un persona, d’un prompt, d’une compétence ou d’un calendrier peut accorder un accès read, write ou admin à une personne ou un groupe par l’API d’accès. Toutes les surfaces partageables utilisent la même boîte de dialogue de partage (consultez Partage), et les administrateurs peuvent limiter les serveurs d’outils enregistrés à des personnes ou des groupes de la même manière. Les ressources restent privées par défaut : le rôle global admin ne donne pas accès au contenu des autres utilisateurs. L’appartenance est évaluée au moment de la requête ; retirer un membre révoque donc immédiatement l’accès accordé au groupe. La vue « accès effectif » de l’onglet Gestion des utilisateurs des Paramètres répond à la question « pourquoi cette personne a-t-elle accès à ceci ? » en répertoriant son rôle, ses groupes, ses accès aux fonctionnalités et toutes les autorisations qui lui parviennent.

Journal d’audit de sécurité

Les actions sensibles pour la sécurité — connexions et échecs, déconnexions, révocations de sessions et de jetons, modifications des utilisateurs, groupes, autorisations et jetons — sont enregistrées dans un journal d’audit en ajout seul, distinct de l’analyse d’utilisation. Les détails sont expurgés avant leur stockage : les clés ressemblant à des secrets sont supprimées et la taille des charges utiles est plafonnée. Les mots de passe, jetons et contenu des prompts n’entrent donc jamais dans le journal. Les modifications des groupes et des autorisations écrivent leur événement d’audit dans la même transaction de base de données ; une modification ne peut donc pas exister sans trace. Les administrateurs peuvent consulter le journal depuis l’onglet Gestion des utilisateurs des Paramètres ; sa durée de conservation est de 180 jours par défaut (AUDIT_RETENTION_DAYS).

Sessions

Le serveur dorsal signe les JWT avec JWT_SECRET. Définissez un secret stable en production :

JWT_SECRET=replace-with-a-long-random-secret

Modifier JWT_SECRET invalide les sessions existantes. Les jetons de connexion locale et OAuth utilisent JWT_EXPIRES_IN, dont la valeur par défaut est 7d ; toute modification touche les nouvelles sessions. Les connexions WebSocket échangent le jeton durable contre un ticket à usage unique de courte durée et se ferment à l’expiration de la session sous-jacente.

Chaque connexion crée également un enregistrement de session côté serveur, intégré au JWT. Paramètres → Sessions répertorie chaque appareil avec sa méthode de connexion, sa première et sa dernière activité ainsi que son expiration. Révoquer une session depuis cette page (ou « Déconnecter les autres sessions ») invalide immédiatement son jeton sur toutes les répliques et ferme ses connexions WebSocket actives ; la déconnexion révoque la session actuelle de la même manière. Les jetons émis avant cette fonctionnalité ne contiennent aucun identifiant de session et restent valides jusqu’à leur expiration, sauf si l’action « Déconnecter les autres sessions » effectuée depuis une nouvelle connexion définit aussi une date limite propre au compte qui les refuse.

Authentification à deux facteurs et clés d’accès

Paramètres → Sessions gère les facteurs supplémentaires et la connexion sans mot de passe :

  • Application d’authentification (TOTP). L’inscription affiche un secret base32 et un lien otpauth:// utilisables dans toute application d’authentification ; la confirmation du premier code à 6 chiffres l’active et révèle dix codes de récupération à usage unique. Ensuite, une connexion par mot de passe renvoie un défi de courte durée au lieu d’une session, et POST /api/auth/mfa/verify termine la connexion avec un code TOTP ou un code de récupération. L’intervalle de temps de chaque code accepté est enregistré afin qu’un code intercepté ne puisse pas être rejoué ; les codes de récupération ne sont stockés que sous forme de jetons de recherche unidirectionnels avec clé, et chacun ne fonctionne qu’une fois. La désactivation ou la régénération des codes de récupération exige de prouver de nouveau un facteur.
  • Clés d’accès (WebAuthn). « Se connecter avec une clé d’accès » effectue une connexion sans mot de passe à l’aide d’un identifiant détectable ; la vérification de l’utilisateur (verrouillage de l’écran, biométrie ou PIN) est requise à l’enregistrement et à la connexion. L’attestation none est acceptée, les identifiants ES256 et EdDSA sont pris en charge, et les données d’identification sont chiffrées au repos tandis que l’identifiant est conservé comme jeton de recherche avec clé. Les défis sont à usage unique et expirent après cinq minutes ; un compteur de signatures non nul qui n’augmente pas est refusé comme signe de clonage. Les clés d’accès exigent une origine sécurisée (HTTPS), ou localhost en développement ; définissez WEBAUTHN_RP_ID lorsque l’instance est accessible sous plusieurs noms d’hôte.

Le jeton de défi MFA émis après un mot de passe correct est signé avec un secret dérivé de JWT_SECRET, mais distinct de celui-ci : il ne peut jamais authentifier une requête d’API, est lié à un seul compte et à une seule finalité, et est consommé en cas de réussite.

Les administrateurs peuvent exiger un deuxième facteur pour tous les comptes (Utilisateurs → carte de politique à deux facteurs, ou en le fixant avec MFA_REQUIRED_MODE=required). Lors de leur prochaine connexion, les utilisateurs qui n’en possèdent pas sont accompagnés dans l’inscription avant l’émission d’une session. Pour récupérer un compte, les administrateurs peuvent aussi réinitialiser l’inscription TOTP d’une personne depuis la liste des utilisateurs ; les clés d’accès restent en place, car leur propriétaire les gère dans les paramètres. L’inscription, l’activation, les échecs de vérification, la désactivation, les changements de politique, l’enregistrement ou la suppression des clés d’accès et les réinitialisations par un administrateur sont tous consignés dans le journal d’audit de sécurité.

MFA s’applique aux connexions par mot de passe. Les connexions OAuth et OIDC reposent sur le deuxième facteur de leur fournisseur d’identité et ne sont pas soumises à un autre défi. Les jetons d’API ne sont pas concernés : ils n’utilisent jamais l’authentification de session.

Jetons d’API

Paramètres → Clés d’API émet des jetons d’accès personnels (préfixe lwk_) pour une utilisation par programme. Le secret n’est affiché qu’une fois et n’est stocké que sous forme de hachage. Chaque jeton comporte une liste explicite de portées (chat, models, documents, notes, personas, media, work, admin) ; le serveur dorsal associe chaque famille de routes à une portée requise. Un jeton limité aux notes ne peut donc accéder ni aux discussions ni à l’administration, et la gestion des sessions n’est jamais accessible avec un jeton. Les jetons peuvent avoir une date d’expiration facultative, enregistrent leur dernière utilisation, peuvent être révoqués à tout moment et sont soumis à une limitation de débit propre au jeton sur toutes les répliques. Seuls les administrateurs peuvent émettre des jetons avec la portée d’administration, et le compte doit toujours avoir le rôle administrateur lors de leur utilisation. Un jeton de portée chat sert également de clé pour l’API publique /v1 compatible avec OpenAI.

Cloudflare Turnstile

Turnstile protège la connexion par mot de passe et l’inscription lorsque les deux clés sont configurées :

TURNSTILE_SITE_KEY=...
TURNSTILE_SECRET_KEY=...
TURNSTILE_EXPECTED_HOSTNAME=chat.example.com

L’interface attribue des actions login et signup distinctes. Le serveur dorsal vérifie le jeton auprès de Cloudflare et refuse toute réponse dont le nom d’hôte ou l’action ne correspond pas à la requête. BASE_URL fournit le nom d’hôte attendu lorsque TURNSTILE_EXPECTED_HOSTNAME n’est pas défini explicitement.

Turnstile est désactivé si l’une des clés manque.

OAuth GitHub

Configurez :

GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...
GITHUB_CALLBACK_URL=https://your-domain.example/api/auth/oauth/github/callback

Le parcours OAuth GitHub crée des utilisateurs locaux dont le nom est préfixé par gh_ et leur attribue le rôle user par défaut.

OAuth Hugging Face

Configurez :

HUGGINGFACE_CLIENT_ID=...
HUGGINGFACE_CLIENT_SECRET=...
HUGGINGFACE_CALLBACK_URL=https://your-domain.example/api/auth/oauth/huggingface/callback

Le parcours OAuth Hugging Face crée des utilisateurs locaux dont le nom est préfixé par hf_ et leur attribue le rôle user par défaut.

Les deux fournisseurs OAuth utilisent une valeur state aléatoire et cryptographiquement sûre, liée à un cookie SameSite HttpOnly de courte durée. Le rappel refuse un état manquant ou différent. Après un rappel réussi, le JWT revient vers l’interface dans un cookie HttpOnly de 60 secondes, immédiatement échangé puis supprimé ; les jetons Bearer ne sont jamais placés dans les URL de rappel, l’historique du navigateur ou les en-têtes de référent.

Redirections et CORS

Définissez BASE_URL pour les valeurs de rappel par défaut et CORS_ORIGIN pour l’accès par navigateur :

BASE_URL=https://your-domain.example
CORS_ORIGIN=https://your-domain.example

Pour le développement local, incluez l’origine du serveur de développement Vite :

CORS_ORIGIN=http://localhost:5173,http://127.0.0.1:5173

Mode démo

Le mode démo est un mode de prévisualisation de l’interface. Il préremplit des identifiants de démonstration désactivés et utilise des réponses d’API fictives. Ce n’est pas un mode d’authentification pour la production.

Liste de contrôle de sécurité

  • Définissez un JWT_SECRET robuste.
  • Conservez DATA_DIR dans un stockage persistant dont l’accès est contrôlé.
  • Sauvegardez ENCRYPTION_KEY avec la base de données.
  • Configurez Turnstile pour l’inscription publique.
  • Utilisez HTTPS pour les déploiements publics.
  • Limitez les clés d’API des fournisseurs au périmètre strictement nécessaire.
  • Veillez à l’exactitude des URL de rappel OAuth.
  • N’accordez l’accès à Work (comptes administrateurs ou mode ouvert à tout le monde) qu’aux personnes de confiance habilitées à exploiter l’environnement d’exécution de conteneurs du serveur dorsal.

Documentation connexe