Capture_dcran_du_20240117_013445.png

En route vers ActivityPods 2.0

Publié le 24.11.2023
Résumé Depuis cet été, grâce à une subvention de NLnet obtenue dans le cadre du programme NGI0 Entrust Fund, nous travaillons sur la version 2.0 d’ActivityPods, avec une sortie prévue au printemps 2024. Cet article a pour objectif d’expliquer ce travail de fond et ses enjeux.
Billet En préambule, il nous semble important de préciser que, lors du développement de la première version d’ActivityPods, nous avons dû faire des choix que nous savions ne pas être “scalables” ou sécurisés. Mais notre volonté à ce moment était de sortir des applications fonctionnelles dans un temps relativement court. La v1 a en effet été développée bénévolement fin 2021 sur une durée de 3 mois, et nos finances ne nous permettaient pas, à ce moment, d’en faire plus.

Cette stratégie fut un succès: sur la région de Compiègne, les applications Bienvenue chez moi et L’Entraide sont aujourd’hui utilisées par une communauté d’environ 500 personnes, qui ont chacune un Pod – parfois sans le savoir ! Depuis 2 ans, les performances ont toujours été bonnes, il n’y a eu que quelques bugs, et surtout cela a permis de tester l’architecture avec un cas concret.

Néanmoins il reste quelques problèmes fondamentaux qu’il est important de régler, comme nous allons le voir maintenant.

Des applications externalisées

Dans la v1, les applications ActivityPods sont uniquement frontend, et elles comptent sur du code backend se trouvant dans l’hébergeur de Pods (donc dans le dépôt principal d’ActivityPods) pour gérer correctement certains “effets secondaires” qui ne peuvent être gérés par le frontend.

Par exemple, lorsqu’un événement sur Bienvenue chez moi atteint le nombre de participants maximum, il est marqué comme “fermé” et les invités ne peuvent plus s’inscrire. Autre cas de figure: pour une application Open Badges que nous avons développée dans le cadre du projet ActivityBadges, la génération d’Open Badges ne peut se faire que côté backend. Pour le moment, c’est donc à l’hébergeur de Pod de gérer ça.

Cette solution n’est clairement pas scalable puisque, si une nouvelle application est déployée (ou mise à jour), il faut impérativement que tous les hébergeurs de Pods mettent à jour ActivityPods. Cela implique une coordination et une confiance qui est possible sur un petit terrain d’expérimentation, mais inenvisageable à plus grande échelle.

Dans la v2, les applications auront toutes une partie backend où se trouvera le code qui leur est spécifique. Cette partie backend comprendra a minima un acteur ActivityPub pour l’application, qui pourra ainsi communiquer avec les Pods (également acteurs ActivityPub).

Nous allons utiliser une partie de la spec interopérabilité de Solid pour permettre aux applications de s’enregistrer auprès du Pod et déclarer leurs besoins d’accès. Pour le moment, l’enregistrement passera par ActivityPub car c’est le plus simple avec notre architecture actuelle. Nous attendons que cette spec soit terminée pour nous y conformer entièrement.

La partie backend aura la possibilité d’écouter ce qui se passe sur le Pod et d’y réagir. En passant par les notifications Solid et des canaux websocket, elle pourra écouter l’inbox et l’outbox ActivityPub de l’utilisateur. Lorsque l’utilisateur créera ou mettra à jour une donnée sur son Pod, cela sera indiqué dans le flux d’activité de son outbox afin de faciliter cette écoute.

Finalement, la partie backend pourra envoyer des notifications à l’utilisateur, en réaction à certaines activités (p.ex. la réception d’une invitation à un événement). Cette notification sera simplement une Note envoyée via ActivityPub à l’utilisateur, qui pourra être transformée en un email ou une notification web push.

Des containers et collections plus flexibles

Dans la v1, les containers LDP contenant les ressources ne pouvaient pas être créés par les applications ou les utilisateurs: il fallait que l’hébergeur de Pods déclare les containers. C’est un problème similaire au précédent, qui était dû à l’architecture trop rigide de SemApps, la boîte à outils sémantique sur laquelle s’appuie ActivityPods.

Le problème a été fixé cet automne côté SemApps, qui est maintenant capable de détecter les containers à la volée selon les données présentes dans le triple store. Cela va permettre une gestion plus flexible des containers LDP, qui pourront être créés dynamiquement selon les besoins.

Ce qui est prévu pour le moment, c’est que les applications déclareront, lors de leur enregistrement, le type de ressources qu’elles souhaitent utiliser (en lecture et/ou en écriture). Cela créera automatiquement un container correspondant, si le container n’existe pas déjà, et les permissions adéquates seront données aux applications concernées. L’utilisateur devra donner son consentement via un écran dédié.

image authscreen.png (54.1kB)
L'écran d'autorisation dans ActivityPods 2.0

Concernant les collections ActivityStreams, très utilisées par ActivityPub et que nous trouvons très pratiques pour indexer des données, le problème est similaire: dans la v1, les applications peuvent déclarer des collections “custom” qui vont s’attacher automatiquement à certains type de ressources, mais la déclaration se fait dans l’hébergeur de Pod grâce à un service interne.

La solution envisagée pour le moment est de développer une API permettant aux applications (désormais externes) de créer elles-mêmes des collections et d’y ajouter ou enlever des éléments. Cette API n’existe pas dans la spécification ActivityPub, mais il y a des propositions qui vont dans ce sens et nous avons l’intention d’y contribuer.

Des token spécifiques et une authentification plus sécurisée

Le dernier gros point noir de la v1 concerne la sécurité. Chaque token émis actuellement donne accès à l’ensemble des données de l’utilisateur, en lecture et écriture. Si une application malicieuse (ou un hacker) récupère ce token, elle peut prendre le contrôle du Pod de l’utilisateur, et potentiellement tout y effacer.

Nous n’étions également pas satisfaits de la manière non-standard et peu sécurisée dont on gérait l’authentification. Les token JWT que nous générions fonctionnaient bien dans une architecture simple de type backend-frontend, mais la sécurité pour une architecture multi-applications était insuffisante.

Cet automne, nous avons donc pris le temps d’étudier les standards OAuth 2.0 et OIDC, notamment grâce à un excellent cours en ligne. Cela nous a permis de mieux comprendre la spécification Solid-OIDC, que nous avions ignorée jusqu’à maintenant faute de temps-cerveau disponible.

Forts de cette compréhension, nous avons implémenté la première partie de la spec Solid-OIDC qui concerne l’authentification. Nous nous sommes appuyés pour cela sur la librairie node-oidc-provider, également utilisée par le Community Solid Server.

image solidoidcflow1024x667.png (82.5kB)
Une petite partie de Solid-OIDC …

Il manque encore l’utilisation du protocole DPoP pour la requête de données. En attendant, nous utilisons l’ID token retourné par le serveur. C’est une mauvaise pratique mais l’intérêt est qu’il contient l’identifiant de l’utilisateur ET de l’application, ce qui permet de limiter l’accès aux données que l’application a le droit de manipuler (pour requêter des resources sur un serveurs distants, il faut toujours passer par un endpoint proxy).

Si le temps et les moyens le permettent, nous finaliserons l’implémentation de Solid-OIDC pour la sortie de la v2, ce qui permettrait à n’importe quelle application Solid de se connecter sur les Pods ActivityPods. L’autre avantage est que les composants frontend de SemApps deviendraient ainsi compatibles Solid, ouvrant leur usage à toute sa communauté !

Le bonus: Mastopod

L’équipe de NLnet a accepté d’inclure dans le financement un développement que nous souhaitons faire depuis longtemps: une application compatible avec toutes les instances Mastodon, mais qui aura la particularité d’héberger les données sur un Pod. Cette application a un nom tout trouvé: Mastopod.

image mastopod800x403.png (0.4MB)
Un Mastopod, d’après l’AI générative

Nous pensons que Mastopod suscitera beaucoup d’intérêt au sein de la communauté ActivityPub. Les développeurs réaliseront qu’avec l’aide du framework ActivityPods, il est très facile de créer des applications compatibles ActivityPub puisque tout le fonctionnement de base (inbox, outbox, authentification, etc.) est déjà géré par le backend. Il n’y a plus qu’à s’occuper de ce qui est spécifique à l’application.

Et surtout, l’utilisateur n’a pas à se recréer un profil et retrouver ses contacts à chaque fois qu’il utilise un nouvel outil, comme c’est le cas actuellement (il faut un compte pour Mastodon, un compte pour Peertube, un compte pour Pixelfed…) Grâce à l’architecture en Pod, il pourra retrouver immédiatement toutes ses données et ses contacts.