Utilisez Discourse en tant que fournisseur d'identité (SSO, DiscourseConnect)

J’ai pu l’utiliser pour créer un système de liaison de compte pour mon serveur Minecraft ! Je pensais partager à quoi ça ressemble ! C’était la première fois que je travaillais avec Discourse SSO, donc j’ai peut-être tout rendu trop compliqué. Cependant, ça fonctionne, ce qui est le principal.

4 « J'aime »

Bonjour, j’ai tout fait correctement. Mais lorsque l’utilisateur n’est pas connecté à Discourse, une fenêtre contextuelle de connexion utilisateur s’affiche. Lorsque je saisis mon nom d’utilisateur et mon mot de passe, je ne suis pas redirigé vers l’URL de retour. Pouvez-vous m’aider s’il vous plaît ?

Je suppose que le nonce est là pour prévenir les attaques par rejeu. J’ai lu en ligne que les attaques par rejeu ne sont pas possibles avec HTTPS, ce que j’utilise. Ai-je donc encore besoin du nonce ? Je demande car je ne sais pas où le stocker. Est-ce logique de le stocker comme un cookie sécurisé en texte clair dans le navigateur de l’utilisateur ? et ensuite le lire depuis le navigateur avec la charge utile de retour ?

Cette bibliothèque, liée depuis le post original GitHub - ArmedGuy/discourse_sso_node: npm package for Discourse SSO login features., n’utilise pas le nonce lors de la validation de l’utilisateur.

Oui, vous devez toujours valider le nonce car il empêche la réutilisation des charges utiles que Discourse envoie lorsqu’il redirige les utilisateurs vers votre site.

Par exemple, supposons que votre site ait du contenu protégé par un mur payant auquel seuls les membres du groupe subscribers sur Discourse peuvent accéder, et que vous utilisiez le champ groups dans la charge utile que Discourse envoie à votre site pour afficher le contenu payant uniquement aux membres du groupe subscribers. Si vous ne validez pas le nonce, un utilisateur qui n’est plus dans le groupe subscribers pourrait utiliser une ancienne charge utile datant de l’époque où il était membre pour se connecter à votre site et voir le contenu payant.

Il est préférable de stocker le nonce dans une base de données avec une date d’expiration courte et de supprimer le nonce de la base de données dès qu’il est utilisé. Cependant, si vous ne pouvez pas utiliser de base de données, vous pouvez utiliser un cookie pour stocker le nonce, mais vous devrez prendre des mesures supplémentaires pour empêcher la réutilisation de la charge utile :

  1. attachez une date d’expiration au nonce lorsque vous le générez, par exemple 10 minutes à partir de l’heure actuelle
  2. signez le cookie entier (nonce + date d’expiration) pour empêcher les utilisateurs de modifier le nonce et/ou la date d’expiration
  3. vérifiez la signature du cookie et assurez-vous que le nonce n’est pas expiré

Cela devrait vous offrir une protection suffisante contre la réutilisation de la charge utile. Gardez à l’esprit qu’il reste techniquement possible de réutiliser une charge utile, mais cela sera limité à une fenêtre de 10 minutes au lieu d’une durée indéfinie.

Une solution plus simple qui ne nécessite pas de cookie consiste à inclure la date d’expiration dans un champ personnalisé dans la charge utile que vous générez. Ensuite, lorsque Discourse redirige les utilisateurs vers votre site avec une charge utile, vos champs personnalisés seront inclus et vous pourrez récupérer la date d’expiration et vérifier qu’elle n’est pas expirée. Pour inclure un champ personnalisé dans la charge utile, vous devez inclure un champ préfixé par custom., donc votre charge utile ressemblerait à ceci :

nonce=NONCE&return_sso_url=URL_DE_RETOUR&custom.expiration_date=TIMESTAMP
4 « J'aime »

Vous pourriez également stocker le nonce dans la session, ce qui empêcherait également l’utilisateur de le falsifier.

3 « J'aime »

Je reviens sur ce fil des années plus tard

Quelqu’un peut-il me dire (@pfaffman ou @tobiaseigen ou @iamntz) ce que le fournisseur SSO de Discourse renvoie ? Je sais que je peux « essayer et voir », mais ce serait bien de l’avoir documenté. Le code d’exemple PHP de GitHub ne mentionne même pas d’autres champs.

Idéalement, il renverrait les mêmes champs que lorsque Discourse utilise le script externe pour le SSO, tels que l’ID externe, l’e-mail, le nom d’utilisateur, le nom, la photo d’avatar, etc. Ainsi, nous pourrions importer cela et créer un utilisateur de notre côté !

Indique-t-il également à WordPress l’e-mail ?

Qu’en est-il des groupes, des badges, etc. ? Pouvons-nous trouver ces informations en effectuant des appels REST ?

Enfin, qu’en est-il des messages privés de l’utilisateur et d’autres choses ? Je suppose que si Discord était un fournisseur oAuth et permettait à nos applications de consommer ces choses, ce serait génial.

Lors de la tentative d’activation de Discourse Connect, j’obtiens cette erreur :
enable_discourse_connect: Vous ne pouvez pas activer DiscourseConnect et l'invitation uniquement en même temps.

Des idées ?

Je vois que vous avez posé la même question ici : Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso) - #537. Si vous essayez de configurer le paramètre enable discourse connect et non le paramètre enable discourse connect provider, l’autre sujet est le bon endroit pour poser votre question.

Le paramètre enable discourse connect provider est destiné à lorsque vous souhaitez utiliser votre site Discourse comme fournisseur d’identité pour un autre site. Le paramètre enable discourse connect est destiné à lorsque vous souhaitez connecter les utilisateurs à Discourse via un site externe.

1 « J'aime »

J’ai implémenté la procédure en Python pour une application Flask que je construis. Voici un code de base pour quiconque en aurait besoin. Les étapes décrites dans ce sujet étaient assez simples à suivre, mais je ne suis pas un spécialiste de la sécurité, donc si j’ai négligé quoi que ce soit, faites-le moi savoir !

2 « J'aime »

Nous essayons de mettre en œuvre l’utilisation de Discourse comme fournisseur SSO et ce que nous ne comprenons pas, c’est comment Discourse sait quel utilisateur doit être vérifié ? Les instructions disent : « Créez une nouvelle charge utile avec un nonce et une URL de retour ». Mais lorsque vous publiez cela via une requête fetch à Discourse, comment Discourse sait-il quel utilisateur vérifier pour voir s’il est connecté ? Désolé si cela semble être une question stupide, mais je ne comprends tout simplement pas comment cela fonctionne et j’ai travaillé avec de nombreux systèmes d’authentification au fil des ans, donc je suis quelque peu familier. L’e-mail de l’utilisateur pour lequel nous essayons de vérifier le statut de connexion doit-il être inclus dans la charge utile envoyée à Discourse ? Si oui, quelle est la structure exacte de la charge utile qui doit être envoyée à Discourse ? Sinon, que vérifie exactement Discourse ? Mon hypothèse est que nous demandons à l’utilisateur son e-mail de notre côté, puis envoyons la charge utile avec l’e-mail à Discourse pour voir si cet utilisateur particulier est connecté, mais ce n’est pas ce que disent les instructions, donc je suis totalement confus. Merci pour toute aide.

Ce n’est pas grave. Nous avons résolu ce problème. Nous pensions que l’URL SSO devait être envoyée en tant que requête POST à l’instance Discourse, puis recevoir une réponse. Maintenant, nous voyons qu’il s’agit d’une redirection vers Discourse, puis Discourse redirige à nouveau vers notre site. Il est donc clair maintenant quoi faire. Désolé pour le message précédent.

3 « J'aime »

Pour information/À titre informatif : J’ai soumis une PR pour autoriser un paramètre prompt=none dans la requête d’authentification. Similaire à une fonctionnalité du protocole OpenID Connect, cela permet à un consommateur SSO de vérifier si un utilisateur/client est déjà connecté, sans l’envoyer à une boîte de dialogue de connexion s’il ne l’est pas.

La PR attend une dernière révision par un membre de l’équipe Discourse depuis environ 8 semaines ; cela semble assez long, plus que ce à quoi je m’attendrais. :crying_cat_face:

7 « J'aime »

Salut @mdoggydog - désolé pour ce très long délai !

Je viens de passer en revue et de fusionner la PR - merci pour ta contribution ! :raised_hands:

3 « J'aime »

Youpi ! Merci, @david.

Comme promis, je viens de mettre à jour l’article wiki ici pour inclure une description du nouveau paramètre (et du paramètre logout précédent, et pour corriger quelques fautes de frappe/grammaire mineures, et pour ajouter une section de références documentant la charge utile sso= telle que je la comprends après avoir fouillé dans le code source).

2 « J'aime »

Je veux arrêter d’utiliser notre site Web comme SSO pour Discourse et utiliser plutôt les outils de connexion intégrés de Discourse pour limiter l’accès à certains éléments de notre site Web.

Je pense que le bon outil à utiliser est : GitHub - discourse/discourse-auth-proxy: An http proxy that uses the DiscourseConnect protocol to authenticate users

Je n’ai pas trouvé d’instructions détaillées sur la façon de l’utiliser.

Puis-je l’installer sur la même gouttelette DigitalOcean que notre site Discourse, ou dois-je l’héberger ailleurs ?

Modifier : J’ai mis ma question en gras :slight_smile:

1 « J'aime »

Une aide concernant la question ci-dessus ? Use Discourse as an identity provider (SSO, DiscourseConnect) - #148 by alehandrof

Je définis return_sso_url sur une URL qui contient elle-même un paramètre de requête :

http://localhost:7000/completeLogin?returnto=%2F

La charge utile que j’envoie à /session/sso_provider en tant que paramètre sso ressemble à ceci avant l’encodage en base64 :

nonce=ENIwf0bElViDu325dTd6&return_sso_url=http://localhost:7000/completeLogin?returnto=%2F

L’URL vers laquelle Discourse redirige réellement après authentification est celle-ci (avec les paramètres sso et sig abrégés) :

http://localhost:7000/completeLogin?returnto=/\u0026sso=...\u0026sig=...

Ce qui me surprend ici, c’est que la chaîne de requête que j’ai définie pour return_sso_url semble avoir été décodée par URL par quelque chose, car elle contient returnto=/ au lieu de returnto=%2F. La valeur de return_sso_url que je trouve à l’intérieur de sso après l’avoir décodée en base64 contient également une barre oblique au lieu de %2F.

Est-ce ce à quoi je dois m’attendre ? (Si oui, pourquoi ?) Est-ce un bug dans Discourse ?

Quelle est la raison pour laquelle la charge utile sso contient avatar_url au lieu de avatar_template tel que retourné dans /u/{username}.json et /session/current.json ?

avatar_url n’est pas présent pour les utilisateurs qui n’ont pas défini d’avatar, alors que avatar_template contient le chemin leter_avatar_proxy réellement utilisé dans Discourse pour afficher les avatars de ces utilisateurs, et avatar_url pointe vers l’image brute de l’avatar au lieu d’une image mise à l’échelle à la taille souhaitée pour les utilisateurs qui ont défini un avatar.

Il me semble que avatar_template est ce que toute personne qui a l’intention d’utiliser les informations d’avatar contenues dans sso voudra — mais devra ensuite faire une demande d’API supplémentaire pour l’obtenir.

2 « J'aime »

Pour le moment, j’implémente le SSO dans mon application, la connexion fonctionne très bien jusqu’à présent, la déconnexion non.

Mon instance Discourse redirige correctement vers l’URL de retour sans aucun paramètre sso ou sig, mais lorsque j’ouvre Discourse, mon compte est toujours connecté.

Des idées ?

Je suppose que vous utilisez le paramètre de site Discourse logout redirect pour rediriger les utilisateurs vers votre application après leur déconnexion de Discourse.

Une cause possible du problème serait si le paramètre login required est activé sur votre site Discourse. Lorsque ce paramètre est activé, Discourse redirigera automatiquement les utilisateurs non authentifiés vers le site du fournisseur SSO s’ils se sont rendus directement sur le site Discourse. Cela signifie que, à moins que vous ne déconnectiez les utilisateurs de votre application lorsqu’ils sont d’abord redirigés vers l’URL logout redirect, ils seront automatiquement connectés à Discourse la prochaine fois qu’ils visiteront le site. Vous pouvez confirmer ce comportement en passant par le processus avec l’inspecteur de votre navigateur ouvert sur son onglet réseau.

Au cas où cela serait utile, voici comment le plugin WP Discourse gère la redirection de déconnexion Discourse : wp-discourse/lib/sso-provider/discourse-sso.php at main · discourse/wp-discourse · GitHub.

2 « J'aime »