Journal Authentifiez-vous sans mot de passe grâce à XMPP, 10 ans plus tard

Posté par  (site web personnel, Mastodon) . Licence CC By‑SA.
9
11
sept.
2025

Bonjour,

J'avais un problème avec mon outil de suivi de bugs.

J'auto-héberge mes projets personnels (ou en tout cas j'essaie, plein de choses se sont retrouvées sur Githib par facilité, et Github est de moins en moins bien, donc je les migre petit à petit vers mon infrastructure personelle, qui est pourtant en place depuis bien avant l'apparition de Github).

Bref, j'avais un problème. Pour cet outil de rapports de bugs auto-hébergé, les utilisateurs doivent se connecter avec un compte. Ça permet de savoir qui est qui, ça limite pas mal le spam, et ça permet de donner des droits d'accès supplémentaires à certains utilisateurs. Au début j'ai géré ça de façon très simple avec une authentification HTTP basique. Ça veut dire que je dois créer à la main un compte pour les utilisateurs qui le demandent, en ajoutant un login et un mot de passe dans un fichier de config du serveur web. Le tout stocké en clair. Ça allait bien quand je n'hébergeais que quelques projets d'étude partagés avec mes camarades de classe. Mais impossible d'utiliser ce système pour des utilisateurs extérieurs qui souhaitent simplement ouvrir un ticket de bug.

Je pourrais utiliser le plugin AccountManager de Trac. Celui-ci permet aux utilisateurs d'enregistrer leur propre compte et de choisir eux-même un mot de passe. Cela suppose que le serveur soit bien configuré, que ces mots de passes soient chiffrés, etc. Mais ça crée aussi un frein qui va dissuader les gens de remonter des problèmes: il faut se créer un compte, probablement résoudre un captcha antispam, etc. Bref, pas moyen de convaincre les gens de quitter Github avec un tel système.

La solution est donc de déléguer l'authentification à quelqu'un d'autre. Il y a quelques années, cela avait été développé de façon intelligente avec le protocole OpenID (c'était la grande époque du Web 2.0). Dans ce protocole, les utilisateurs entrent leur identifiant OpenID qui contient l'URL du fournisseur d'identité de leur choix. Et avec quelques requêtes, on peut valider avec ce fournisseur que l'utilisateur est bien qui il prétend. Malheureusement, OpenID a par la suite été remplacé par OAuth2. Ce dernier fait la même chose, sauf que il n'est plus possible d'accepter n'importe quel fourniseur d'identitité automatiquement. À la place, le site doit obtenir une clé d'API et s'enregistrer avec chaque fournisseur qu'il souhaite utiliser. La conséquence est qu'il ne reste que quelques rare fournisseurs d'identité en utilisation. En gros, on doit avoir le choix entre Google, Github, et Facebook. Que des gens pas très recommandables.

Je me suis donc penché vers XMPP pour voir ce qu'il était possible de faire. Comme vous suivez Linuxfr depuis très longtemps, vous vous souvenez sans doute d'avoir lu cette dépêche de 2016 (ou sinon, c'est seulement maintenant que vous comprenez le titre de ce journal).

Or donc, XMPP propose une extension permettant de faire exactement ce dont j'ai besoin: prouver qu'un utilisateur est bien qui il dit être, en utilisant son adresse XMPP (JID) comme identifiant. Le protocole consiste à envoyer par XMPP une demande de confirmation. Si l'utilisateur l'accepte, le serveur HTTP valide l'authentification. Pas besoin de créer de nouveau compte, de stocker de mot de passe, rien de tout ça.

J'ai constaté que depuis 10 ans, les choses ne semblent pas avoir trop bougé. Il y a toujours deux implémentations de la partie serveur: une sous forme d'un composant XMPP, et l'autre sous forme d'un plugin Wordpress. Et là j'ai encore un problème: je n'utilise pas Wordpress, et je ne dispose pas d'un serveur XMPP sur lequel déployer ce composant. De plus, la méthode avec un composant semble aboutir à une centralisation de l'authorité de confiance vers un seul serveur XMPP ou une petite poignée de serveurs qui déploieraient le composant. Ça me semble pas la meilleure approche.

J'ai donc implémenté ma propre version. Dans mon cas, elle fonctionne plutôt comme une extension du serveur web. Cela est possible grâce à FastCGI utilisé ici en mode "Authorizer". FastCGI (une technologie sortie tout droit des années 90) est un protocole qui permet à un serveur web de déléguer le traitement de certaines requêtes à une application externe. La communication entre les 2 se fait par des sockets UNIX locaux. Le mode "authorizer" permet d'intercepter uniquement la partie "authentification" d'une URL. L'authorizer va envoyer une réponse HTTP 401 avec un challenge WWW-Authenticate, puis, une fois la réponse au challenge reçue, si elle est valide, il va laisser le serveur web renvoyer la page de destination de la requête. Ce composant peut donc facilement se déployer là où habituellement on met une authentification "basic" ou "digest" configurée directement dans le serveur HTTP.

Pour l'implémentation, j'ai choisi d'utiliser Rust. Un petit peu parce que j'avais envie de tester ce langage, mais surtout parce qu'il fournit des bibliothèques faciles à utiliser aussi bien pour l'interfaçage fastcgi (tokio-fastcgi) que pour la partie XMPP (tokio-xmpp). J'ai eu besoin de faire quelques ajouts dans la bibliothèque XMPP pour Rust, mais cela a été assez facile. Et le module d'authentification lui-même ne fait que 330 lignes de code.

Ce composant fastcgi se comporte en même temps comme un client XMPP. Il peut donc envoyer des requête de confirmation sur le réseau XMPP et recevoir les réponses, et ce, sans aucune configuration particulière du serveur XMPP choisi (il faudra simplement y créer un compte que le client utilisera).

D'un poitn de vue utilisation, on reçoit un dialogue d'authentification classique (généré par le navigateur web). C'est pas idéal, parce que ce dialogue demande un login et un mot de passe, alors qu'il faut entrer un JID et un token unique (et certainement pas son mot de passe XMPP). Je réfléchis à comment faire pour remplacer ce dialogue par une page web plus sympathique avec des explications claires (je pense que c'est faisable).

Il ne reste plus qu'à configurer le serveur web pour utiliser cet authorizer. Et donc maintenant, si vous voulez remonter des bugs pour mon client XMPP, c'est possible sans avoir besoin de créer un compte!

Et si vous voulez déployer ça sur votre propre serveur, le code source et la documentation sont également disponibles.

Notez aussi que si vous aimez les mots de passe, il est tout à fait possible d'utiliser cette méthode d'authentification comme second facteur en combinaison avec un login et mot de passe classique. Le tout sans passer par un service centralisé d'un GAFAM.

J'espère que plein de gens vont déployer ce système et que je pourrai me logger un peu partout avec mon JID un jour!

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.