J’ai un plugin JS sur mon site Discourse. Ce JS utilise PocketBase pour stocker des données. PocketBase est un service SQLite « sans serveur » qui me permet de stocker des fichiers et des blobs JSON. PocketBase dispose d’un système d’authentification basé sur JWT formidable, de sorte qu’une fois qu’un utilisateur a un jeton d’authentification, il peut stocker des données en toute sécurité directement dans PocketBase (sans passer par un serveur backend, etc.) directement depuis le JS côté client.
J’essaie de trouver un moyen de générer automatiquement une connexion côté PocketBase lorsqu’un utilisateur se connecte à Discourse.
Ma première tentative a été de faire en sorte que le plugin JS appelle un chemin sur le serveur et inclue les cookies d’authentification Discourse. Ensuite, pour ce chemin, laisser Nginx le proxifier vers un service (« proxy de connexion ») qui peut décoder les cookies d’authentification et déterminer qui est l’utilisateur. Avec les informations utilisateur vérifiées, le proxy de connexion peut alors faire un appel spécial à PocketBase et récupérer un cookie d’authentification PocketBase, puis renvoyer ce cookie d’authentification PocketBase que le JS côté client peut utiliser pour effectuer des requêtes ultérieures directement à PocketBase.
Cependant, j’ai du mal à décoder les cookies d’authentification Discourse (j’imagine que _t est le bon cookie, mais je ne vois pas de moyen simple d’accéder aux détails de l’utilisateur et je crains que la structure ne change de toute façon).
Existe-t-il un moyen plus intelligent d’accéder en toute sécurité à l’adresse e-mail d’un utilisateur connecté ? Je ne pense pas que cela devrait se faire côté client, et je préférerais le faire côté serveur pour des raisons de sécurité évidentes.
Je ne connais pas assez votre stack ou votre cas d’utilisation, mais je pense avoir déjà résolu un problème similaire, et certaines idées pourraient vous être utiles.
J’ai une application Next.js où j’ai besoin que le côté client ait un JWT valide pour effectuer des appels à mon API backend s’il existe une session Discourse.
Dans mon cas, je fais cela avec un seul appel fetch côté client avec { credentials: "include" }, ce qui ne fonctionne que parce que j’ai tout configuré avec un seul domaine et que l’appel fetch suit transparentement les redirections.
Mon client récupère un /auth/token personnalisé, qui vérifie l’existence de _t (juste pour éviter une redirection inutile sinon) et renvoie une redirection vers une URL sécurisée /session/sso_provider construite selon la documentation du sujet lié, avec nonce/sso/sig, et une return_sso_url pointant vers un /auth/callback personnalisé, qui extraira les données envoyées par Discourse, construira et renverra un jeton JWT que mon client pourra utiliser à partir de ce moment-là.
Je pense que votre cas d’utilisation peut être résolu de manière similaire.
@renato Quelques questions si cela ne vous dérange pas.
Cela signifie-t-il que je dois déléguer l’intégralité de l’authentification de la gestion des utilisateurs à l’application Connect ? Je ne suis pas sûr de vouloir faire cela, si c’est le cas.
Si Connect n’est qu’une couche supplémentaire par-dessus la gestion existante de l’authentification des utilisateurs de Discourse, alors cela semble réalisable.
Mais, lorsque j’ai commencé à lire sur Discourse Connect, je crains de devoir maintenant créer et maintenir une toute nouvelle application pour gérer l’authentification des utilisateurs, et je ne sais pas vraiment comment définir la portée de cela pour le moment.
Ma réponse suppose que vous utilisez Discourse comme fournisseur d’identité (avec ses interfaces utilisateur de connexion/inscription) et que vous souhaitez le conserver ainsi.
Du côté de Discourse, l’activer est aussi simple que
Cependant, vous avez mentionné que vous construisez un plugin.
Si vous créez « un chemin sur le serveur » dans une nouvelle action de contrôleur dans un plugin Discourse, vous pouvez obtenir l’utilisateur à partir de la session, appeler des tiers et renvoyer le JWT à votre client.
Mais je pense que c’est si je veux envoyer mes utilisateurs vers un site secondaire et y gérer l’authentification.
Dans mon cas, j’ai un morceau de JS qui s’exécute sur le site Discourse. Et je veux que ce JS appelle une route sur le même serveur et récupère un cookie pour Pocketbase.
J’utilise en fait un proxy Nginx devant Discourse, et j’ai donc juste ajouté une route spéciale /pb/auth (par exemple). Lorsque mon JS atteint cette route, un serveur proxy backend (qui n’est pas dans Discourse) accepte cette connexion et essaie de décoder le cookie de session _t.
Je faisais cela car cela me semblait un peu plus facile que d’ajouter un plugin Discourse (je suis moins familier avec cela et la configuration de développement, etc.). S’il s’agit simplement de décoder un cookie à l’aide du hachage base64 et sha, je pensais que cela me donnerait une charge utile sécurisée pour m’indiquer qui est l’utilisateur.
Mais, si vous pensez qu’il existe un moyen simple de créer un plugin qui ajoute cette route à Discourse, je suis très intéressé à essayer. Cela semble être la bonne approche à long terme. Mais je suis un ancien programmeur Perl, donc je préfère la voie facile, et ma route Nginx semblait plus facile.
Tout le contraire : si vous avez un “site” séparé (PocketBase dans cet exemple) et que vous voulez que Discourse soit la source de vérité pour la gestion des utilisateurs/authentification – comme mon exemple Next.js.
À première vue, je dois demander : ce tutoriel ajoute-t-il du code à l’installation de base de Rails pour Discourse ? Cela me convient si c’est la méthode officielle, mais j’ai l’impression que c’est dangereux et qu’il serait préférable de le gérer comme un plugin (qui peut être facilement désinstallé, désactivé). De plus, ne dois-je pas craindre que cela ne casse les mises à niveau de Discourse si mon code ne se trouve pas dans le dépôt GitHub ?
Par exemple, ici :
Cela signifie-t-il que je dois vraiment entrer dans le conteneur (./launcher enter app) puis modifier /var/www/app/controllers/snack_controller.rb ?
Et, en fait, j’ai suivi ces instructions. Je n’arrive pas à faire fonctionner la route /admin/snack.json, même après avoir exécuté ./launcher rebuild app.
Ce tutoriel semble dater d’environ huit ans. Est-ce vraiment la bonne façon de faire les choses ?
Il existe d’autres guides, la date en haut est la date de création du sujet mais tout ce qui se trouve dans Documentation devrait être à jour – faites-nous savoir si vous trouvez des problèmes.
Vous pouvez consulter le code du Plugin existant à titre de référence.
Ok, j’ai essayé de suivre les instructions. J’ai essayé d’utiliser cette commande rake plugin:create[pocketbase-auth]à l’intérieur du conteneur (puisque rake ne serait pas disponible à l’extérieur, n’est-ce pas). Mais, cela échoue lamentablement car je n’ai pas git configuré à l’intérieur du conteneur.
En lisant plus loin, il semble que je doive spécifier le dépôt git du plugin pour afficher un plugin dans la section admin. Cependant, je ne suis pas encore arrivé au point où j’ai même une version à peine fonctionnelle du plugin et je n’ai pas les choses dans un dépôt git.
EDIT : Je n’ai pas lu attentivement, et en effet cela nécessite une configuration de développement, ce qui est clairement indiqué dès le départ. Je vais travailler là-dessus et revenir à cela.
Je soupçonne que ces difficultés sont dues au fait que les plugins sont généralement développés par rapport à une configuration “dev” de discourse, et non à l’intérieur du conteneur docker que j’utilise. Ce n’est pas grave, mais j’aimerais que les guides de développement de plugins commencent avec cette hypothèse et des instructions sur la façon de fonctionner de cette manière. La façon recommandée d’exécuter discourse est d’utiliser docker (que j’adore), mais je pense qu’il y a un décalage entre la façon d’exécuter les choses à l’intérieur de docker et de faire du développement à l’intérieur des documents.
# rake plugin:create[pocketbase-auth]
Cloning 'https://github.com/discourse/discourse-plugin-skeleton' to '/var/www/discourse/plugins/pocketbase-auth'...
Initializing git repository...
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /var/www/discourse/plugins/pocketbase-auth/.git/
Author identity unknown
*** Please tell me who you are.
Run
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
to set your account's default identity.
Omit --global to set the identity only in this repository.
fatal: unable to auto-detect email address (got 'discourse@community-public-do-vm-app.(none)')
rake aborted!
Command failed with exit 128: git
/var/www/discourse/lib/tasks/plugin.rake:356:in `system'
/var/www/discourse/lib/tasks/plugin.rake:356:in `block (2 levels) in <main>'
/var/www/discourse/lib/tasks/plugin.rake:346:in `chdir'
/var/www/discourse/lib/tasks/plugin.rake:346:in `block in <main>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'
Tasks: TOP => plugin:create
(See full trace by running task with --trace)
Une mise à jour : j’ai suivi votre conseil et développé un plugin. Il fonctionne très bien et fait exactement ce dont j’avais besoin. Merci pour votre aide.