Bonjour ! Nous avons développé un plugin SSO personnalisé pour regrouper les informations de connexion de notre entreprise dans un package utilisable par Discourse pour gérer les connexions et créer des comptes. Avec la version v2.7.0beta4, nous avons commencé à recevoir des erreurs indiquant que nous ne fournissions pas un nouveau paramètre : secure_session. Je ne trouve aucune information sur le format attendu de ce paramètre ni sur son contenu. Existe-t-il une documentation supplémentaire concernant cette mise à jour ?
Connaissez-vous le message d’erreur exact que vous rencontrez ? À ma connaissance, Discourse associe désormais le paramètre nonce SSO à la session de l’utilisateur. Cela signifie que si une application génère le nonce en effectuant une requête en arrière-plan vers /session/sso, ce nonce ne sera pas valide. Il est possible que ce soit le problème que vous rencontrez.
Le fichier service_gateway_current_user.rb fait partie de notre plugin servant à construire la charge utile à envoyer à DiscourseSingleSignOn en se basant sur les en-têtes « Service Gateway » (« Service Gateway » étant notre structure interne pour déterminer si vous êtes connecté à notre système).
Pour expliquer cette partie de la pile :
Notre fonction current_user utilise nos en-têtes pour rechercher un SingleSignOnRecord dont l’external_id correspond à l’ID utilisateur dans les en-têtes. Si ce n’est pas le cas, nous passons à la section create_sso_record.
create_sso_record crée un hachage – { external_id: sg_headers[:user_id], email: sg_headers[:email] } – et l’envoie à notre fonction upsert_sso_record.
upsert_sso_record prend ce hachage (payload dans le contexte ci-dessous) et tente de créer un objet DiscourseSingleSignOn :
def upsert_sso_record(payload)
encoded_query = Base64.encode64(payload.to_query)
sig = OpenSSL::HMAC.hexdigest('sha256', ENV['SSO_SECRET'], encoded_query)
sso = DiscourseSingleSignOn.parse({ sso: encoded_query, sig: sig }.to_query)
if SiteSetting.verbose_sso_logging
Rails.logger.warn("Verbose SSO log: Started SSO process\n\n#{sso.diagnostics}")
Rails.logger.warn("SSO Payload:\n\n#{payload}")
end
begin
user = sso.lookup_or_create_user(@request.ip)
rescue ActiveRecord::RecordInvalid => ex
Rails.logger.error "Unable to find/create sso user #{ex}"
end
user
end
L’appel à parse sur la 3e ligne de cette fonction est là où le problème semble se produire. Dès qu’il tente d’initialize l’objet, la valeur secure_session attendue n’est pas présente.
Je me demande si la modification du paramètre de site discourse_connect_csrf_protection à false résoudra le problème pour vous. Ce paramètre de site est masqué, il doit donc être défini depuis la console Rails. Vous pouvez trouver des détails à ce sujet dans les réponses à ce sujet : DiscourseConnect flow no longer functions.
Malheureusement, je ne pense pas que ce nouveau paramètre suffira à lui seul : les détails internes du code nécessiteront toujours la transmission d’un objet secure_session, même s’il n’est pas utilisé.
En général, nous recommandons d’utiliser les hooks officiels pour les plugins d’authentification, plutôt que de remplacer l’implémentation de DiscourseConnect du cœur.
Il est difficile d’être certain sans voir l’intégralité du plugin, mais vous pourriez essayer de transmettre une valeur nil pour secure_session. Cela, combiné à l’activation du nouveau paramètre du site, pourrait aider à rapprocher les choses du bon fonctionnement.
Après avoir examiné davantage le code de v2.7.0.beta4, je vois que ApplicationController contient une définition secure_session. Modifier notre code de plugin comme suit semble fonctionner dans notre environnement de staging :
sso = DiscourseSingleSignOn.parse({ sso: encoded_query, sig: sig }.to_query, secure_session: secure_session)