DiscourseConnect ist eine Kernfunktion von Discourse, mit der Sie „Single Sign-On (SSO)“ konfigurieren können, um die gesamte Benutzerregistrierung und -anmeldung von Discourse vollständig auf eine andere Site auszulagern. Verfügbar für unsere Pro-, Business- und Enterprise-Hosting-Kunden.
(Februar 2021) „Discourse SSO“ heißt jetzt „DiscourseConnect“. Wenn Sie eine alte Version von Discourse verwenden, heißen die Einstellungen unten
sso_...stattdiscourse_connect_....
Das Problem
Viele Sites, die sich mit einer Discourse-Site integrieren möchten, wollen die gesamte Benutzerregistrierung auf einer separaten Site halten. In einem solchen Setup sollten alle Anmeldevorgänge auf diese andere Site ausgelagert werden.
Was ist, wenn ich SSO in Verbindung mit einer bestehenden Authentifizierung nutzen möchte?
Die Absicht hinter DiscourseConnect ist es, die Discourse-Authentifizierung zu ersetzen. Wenn Sie einen neuen Anbieter hinzufügen möchten, sehen Sie sich bestehende Plugins an, wie zum Beispiel: Discourse VK Authentication (vkontakte)
Aktivierung von DiscourseConnect
Um DiscourseConnect zu aktivieren, müssen Sie drei Einstellungen ausfüllen:
enable_discourse_connect: Muss aktiviert sein (globaler Schalter).
discourse_connect_url: Die externe URL, zu der Benutzer weitergeleitet werden, wenn sie sich anmelden möchten.
discourse_connect_secret: Ein geheimer String, der zum Hashen von SSO-Payloads verwendet wird. Stellt sicher, dass die Payloads authentisch sind.
Sobald enable_discourse_connect auf true gesetzt ist:
- Das Klicken auf „Anmelden“ oder das Avatar-Bild leitet Sie auf
/session/ssoum, was wiederum die Benutzer mit einer signierten Payload aufdiscourse_connect_urlweiterleitet. - Benutzern wird nicht erlaubt, ihr „Passwort zu ändern“. Dieses Feld wird aus dem Benutzerprofil entfernt.
- Benutzer können die Discourse-Authentifizierung (Benutzername/Passwort, Google usw.) nicht mehr verwenden.
Was ist, wenn ich es versehentlich aktiviere?
Siehe: Log back in as admin after locking yourself out with read-only mode or an invalid SSO configuration
Implementierung von DiscourseConnect auf Ihrer Site
Discourse verwendet E-Mail-Adressen, um externe Benutzer Discourse-Benutzern zuzuordnen, und geht davon aus, dass externe E-Mails sicher sind. WENN SIE E-MAIL-ADRESSEN NICHT VOR DEM SENDEN AN DISCOURSE VALIDIEREN, IST IHRE SITE EXTREM ANFÄLLIG!
Alternativ, wenn Sie darauf bestehen, nicht validierte E-Mails zu senden, STELLEN SIE SICHER, dass Sie require_activation=true setzen. Dies erzwingt, dass alle E-Mails von Discourse validiert werden. WIR RATEN IMMER NOCH DRINGEND DAVON AB, DIESES VORZUGEN. Wenn Sie also mit dieser Einstellung fortfahren, gehen Sie ein erhebliches Risiko ein.
Discourse leitet Clients mit einer signierten Payload auf discourse_connect_url um (angenommen, discourse_connect_url ist https://somesite.com/sso):
Sie erhalten eingehenden Verkehr mit folgendem Format:
https://somesite.com/sso?sso=PAYLOAD&sig=SIG
Die Payload ist ein Base64-kodierter String, der eine Nonce und eine return_sso_url enthält. Die Payload ist immer eine gültige Query-String.
Zum Beispiel, wenn die Nonce ABCD ist, lautet der rohe Payload:
nonce=ABCD&return_sso_url=https%3A%2F%2Fdiscourse_site%2Fsession%2Fsso_login. Dieser rohe Payload ist Base64-kodiert.
Der aufgerufene Endpunkt muss:
- Die Signatur validieren: Stellen Sie sicher, dass der HMAC-SHA256 von
PAYLOAD(unter Verwendung vondiscourse_connect_secretals Schlüssel) gleich demsigist (sigist hex-kodiert). - Die erforderliche Authentifizierung durchführen.
- Einen neuen URL-kodierten Payload mit mindestens nonce, email und external_id erstellen. Sie können auch zusätzliche Daten angeben. Hier ist eine Liste aller Schlüssel, die Discourse versteht:
- nonce sollte aus der Eingabe-Payload kopiert werden.
- email muss eine verifizierte E-Mail-Adresse sein. Wenn die E-Mail-Adresse nicht verifiziert ist, setzen Sie require_activation auf „true“.
- external_id ist ein beliebiger String, der für den Benutzer eindeutig ist und sich nie ändert, auch wenn sich seine E-Mail, sein Name usw. ändern. Der vorgeschlagene Wert ist die „id“-Zeilennummer Ihrer Datenbank.
- username wird zum Benutzernamen auf Discourse, wenn der Benutzer neu ist oder
SiteSetting.auth_overrides_usernamegesetzt ist. - name wird zum vollständigen Namen auf Discourse, wenn der Benutzer neu ist oder
SiteSetting.auth_overrides_namegesetzt ist. - avatar_url wird heruntergeladen und als Avatar des Benutzers festgelegt, wenn der Benutzer neu ist oder
SiteSetting.discourse_connect_overrides_avatargesetzt ist. - avatar_force_update ist ein boolesches Feld. Wenn es auf
truegesetzt ist, zwingt es Discourse, den Avatar des Benutzers zu aktualisieren, unabhängig davon, ob sichavatar_urlgeändert hat oder nicht. - bio wird zum Inhalt der Bio des Benutzers, wenn der Benutzer neu ist, seine Bio leer ist oder
SiteSetting.discourse_connect_overrides_biogesetzt ist. - title setzt den Titel des Benutzers.
- website setzt die Website des Benutzers in seinem Profil.
- location setzt den Standort des Benutzers in seinem Profil.
- profile_background_url wird heruntergeladen und als Profilhintergrund des Benutzers festgelegt, wenn der Benutzer neu ist oder
SiteSetting.discourse_connect_overrides_profile_backgroundgesetzt ist. - card_background_url wird heruntergeladen und als Kartenhintergrund des Benutzers festgelegt, wenn der Benutzer neu ist oder
SiteSetting.discourse_connect_overrides_card_backgroundgesetzt ist. - locale setzt die Spracheinstellung des Benutzers, wenn der Benutzer neu ist und
SiteSetting.allow_user_localeaktiviert ist. - locale_force_update ist ein boolesches Feld. Wenn es zusammen mit locale auf
truegesetzt ist, erzwingt es die Aktualisierung der Spracheinstellung für bestehende Benutzer (erfordertSiteSetting.allow_user_locale). - Zusätzliche boolesche Felder („true“ oder „false“) sind: admin, moderator, suppress_welcome_message, logout.
- Den Payload Base64-kodieren.
- Einen HMAC-SHA256-Hash des Payloads berechnen, wobei
discourse_connect_secretals Schlüssel und der Base64-kodierte Payload als Text verwendet wird. - Zurück auf die
return_sso_urlmit einemsso- undsig-Query-Parameter umleiten (http://discourse_site/session/sso_login?sso=payload&sig=sig).
Discourse validiert, dass die Nonce gültig ist, und wenn ja, verfallen sie sofort, sodass sie nicht erneut verwendet werden kann. Anschließend versucht es:
- Den Benutzer anzumelden, indem es nach einer bereits verknüpften external_id im
SingleSignOnRecord-Modell sucht. - Den Benutzer anzumelden, indem die bereitgestellte E-Mail verwendet wird (Aktualisierung der external_id) (es sei denn, require_activation = true).
- Ein neues Konto für den Benutzer zu erstellen (E-Mail, Benutzername, Name) und die external_id zu aktualisieren.
Sicherheitsbedenken
Die Nonce (Einmal-Token) verfällt automatisch nach 30 Minuten. Das bedeutet, dass der Benutzer, sobald er auf Ihre Site weitergeleitet wird, 30 Minuten Zeit hat, sich anzumelden oder ein neues Konto zu erstellen.
Das Protokoll ist sicher gegen Replay-Angriffe, da die Nonce nur einmal verwendet werden kann. Die Nonce ist an die aktuelle Browsersitzung gebunden, um CSRF-Angriffe zu verhindern.
Festlegung der Gruppenmitgliedschaft
Wenn die Option discourse connect overrides groups angegeben ist, berücksichtigt Discourse die durch Kommas getrennte Liste der Gruppen, die in groups übergeben werden.
Neben groups können Sie die Gruppenmitgliedschaft auch in Ihrer SSO-Payload mit den Attributen add_groups und remove_groups angeben, unabhängig von der Option discourse connect overrides groups.
add_groups ist eine durch Kommas getrennte Liste von Gruppennamen, für die wir sicherstellen, dass der Benutzer Mitglied ist.
remove_groups ist eine durch Kommas getrennte Liste von Gruppennamen, für die wir sicherstellen, dass der Benutzer kein Mitglied ist.
Referenzimplementierung
Discourse enthält eine Referenzimplementierung der SSO-Klasse:
Eine triviale Implementierung wäre:
class DiscourseSsoController < ApplicationController
def sso
secret = "MY_SECRET_STRING"
sso = DiscourseApi::SingleSignOn.parse(request.query_string, secret)
sso.email = "user@email.com"
sso.name = "Bill Hicks"
sso.username = "bill@hicks.com"
sso.external_id = "123" # eindeutige ID für jeden Benutzer Ihrer Anwendung
sso.sso_secret = secret
redirect_to sso.to_url("http://l.discourse/session/sso_login")
end
end
Übergang zu und von Single Sign-On.
Solange der Parameter require_activation im Anfrage-Payload nicht auf true gesetzt ist, vertraut das System den vom Single Sign-On-Endpunkt bereitgestellten E-Mails. Das bedeutet, dass, wenn Sie in der Vergangenheit ein bestehendes Konto auf Discourse mit deaktiviertem DiscourseConnect hatten, DiscourseConnect dieses einfach wiederverwendet und die Erstellung eines neuen Kontos vermeidet.
Wenn Sie DiscourseConnect jemals deaktivieren, können Benutzer ihre Passwörter zurücksetzen und wieder Zugriff auf ihre Konten erhalten.
Beispiel aus der Praxis:
Gegeben sind folgende Einstellungen:
Discourse-Domain: http://discuss.example.com
DiscourseConnect-URL: http://www.example.com/discourse/sso
DiscourseConnect-Geheimnis: d836444a9e4084d5b224a60c208dce14
E-Mail validiert: Nein (fügen Sie require_activation=true zum Payload hinzu)
Benutzer versucht, sich anzumelden
-
Nonce wird generiert:
cb68251eefb5211e58c00ff1395f0c0b -
Roher Payload wird generiert:
nonce=cb68251eefb5211e58c00ff1395f0c0b -
Payload wird Base64-kodiert:
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI= -
Payload wird URL-kodiert:
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI%3D -
HMAC-SHA256 wird auf dem Base64-kodierten Payload generiert:
1ce1494f94484b6f6a092be9b15ccc1cdafb1f8460a3838fbb0e0883c4390471
Schließlich wird der Browser weitergeleitet zu:
http://www.example.com/discourse/sso?sso=bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI%3D&sig=1ce1494f94484b6f6a092be9b15ccc1cdafb1f8460a3838fbb0e0883c4390471
Am anderen Ende
- Payload wird mit HMAC-SHA256 validiert. Wenn die Signatur nicht übereinstimmt, wird der Prozess abgebrochen.
- Durch Umkehren der oben genannten Schritte wird die Nonce extrahiert.
Benutzer meldet sich an:
name: sam
external_id: hello123
email: test@test.com
username: samsam
require_activation: true
Nicht signierter Payload wird generiert:
nonce=cb68251eefb5211e58c00ff1395f0c0b&name=sam&username=samsam&email=test%40test.com&external_id=hello123&require_activation=true
Die Reihenfolge ist nicht wichtig, Werte sind URL-kodiert.
Payload wird Base64-kodiert:
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGImbmFtZT1zYW0mdXNlcm5hbWU9c2Ftc2FtJmVtYWlsPXRlc3QlNDB0ZXN0LmNvbSZleHRlcm5hbF9pZD1oZWxsbzEyMyZyZXF1aXJlX2FjdGl2YXRpb249dHJ1ZQ==
Payload wird URL-kodiert:
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGImbmFtZT1zYW0mdXNlcm5hbWU9c2Ftc2FtJmVtYWlsPXRlc3QlNDB0ZXN0LmNvbSZleHRlcm5hbF9pZD1oZWxsbzEyMyZyZXF1aXJlX2FjdGl2YXRpb249dHJ1ZQ%3D%3D
Base64-kodierter Payload wird signiert:
3d7e5ac755a87ae3ccf90272644ed2207984db03cf020377c8b92ff51be3abc3
Browser leitet weiter zu:
http://discuss.example.com/session/sso_login?sso=bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGImbmFtZT1zYW0mdXNlcm5hbWU9c2Ftc2FtJmVtYWlsPXRlc3QlNDB0ZXN0LmNvbSZleHRlcm5hbF9pZD1oZWxsbzEyMyZyZXF1aXJlX2FjdGl2YXRpb249dHJ1ZQ%3D%3D&sig=3d7e5ac755a87ae3ccf90272644ed2207984db03cf020377c8b92ff51be3abc3
Synchronisierung von DiscourseConnect-Datensätzen
Sie können den POST-Admin-Endpunkt /admin/users/sync_sso verwenden, um einen DiscourseConnect-Datensatz zu synchronisieren. Übergeben Sie denselben Datensatz, den Sie auch an den DiscourseConnect-Endpunkt übergeben würden; die Nonce spielt keine Rolle.
Wenn Sie admin/users/sync_sso von einer anderen Site aus aufrufen, müssen Sie einen gültigen Admin-api_key und einen gültigen api_username in den Kopfzeilen der Anfrage angeben. Weitere Details zur Struktur der Anfrage finden Sie unter Sync DiscourseConnect user data with the sync_sso route.
Löschen von DiscourseConnect-Datensätzen
Wenn sich Ihre external_id-Werte von Ihrem DiscourseConnect-Anbieter geändert haben (vielleicht haben Sie den Generierungsalgorithmus geändert oder es ist ein anderer Endpunkt), können Sie sicher alle bestehenden Datensätze über die Rails-Konsole entfernen:
SingleSignOnRecord.destroy_all
Abmelden von Benutzern
Sie können den POST-Admin-Endpunkt /admin/users/{USER_ID}/log_out verwenden, um bei Bedarf jeden Benutzer im System abzumelden.
Um den Endpunkt zu konfigurieren, zu dem Discourse bei der Abmeldung weiterleitet, suchen Sie nach der Einstellung „logout redirect“. Wenn hier keine URL festgelegt ist, werden Sie zurück zur in discourse connect url konfigurierten URL weitergeleitet.
Benutzer nach external_id suchen
Benutzerprofildaten können über den Endpunkt /users/by-external/{EXTERNAL_ID}.json abgerufen werden. Dies gibt eine JSON-Payload zurück, die die Benutzerinformationen enthält, einschließlich der user_id, die mit dem log_out-Endpunkt verwendet werden kann.
Bestehende Implementierungen
-
Das
discourse_api-Gem kann für SSO verwendet werden. Schauen Sie sich den SSO-Code im examples-Verzeichnis an, um eine grundlegende Implementierung zu sehen. -
Unser WordPress-Plugin erleichtert die Konfiguration von SSO zwischen WordPress und Discourse. Details zur Einrichtung finden Sie auf der SSO-Registerkarte der Optionsseite des Plugins.
Zukünftige Arbeiten
- Wir möchten mehr Referenzimplementierungen für SSO auf anderen Plattformen sammeln. Wenn Sie eine haben, posten Sie sie bitte in der Dev / SSO-Kategorie.
Erweiterte Funktionen
- Sie können benutzerdefinierte Benutzerfelder übergeben, indem Sie den Feldnamen mit
customprefixieren. Zum Beispiel kanncustom.user_field_1verwendet werden, um den Wert desUserCustomFieldmit dem Namenuser_field_1festzulegen. - Sie können
avatar_urlübergeben, um den Benutzer-Avatar zu überschreiben (SiteSetting.discourse_connect_overrides_avatarmuss aktiviert sein). Avatare werden zwischengespeichert, also übergeben Sieavatar_force_update=true, um sie zu aktualisieren, wenn die URL gleich ist. Derzeit können Sie keine leere URL übergeben, um den Avatar des Benutzers zu deaktivieren. - Standardmäßig wird die Willkommensnachricht an alle neuen Benutzer gesendet, die über SSO erstellt wurden. Wenn Sie dies unterdrücken möchten, können Sie
suppress_welcome_message=trueübergeben. - Um Ihre Discourse-Instanz als DiscourseConnect-Anbieter zu konfigurieren, siehe: DiscourseConnect als Identity Provider verwenden.
Debugging Ihres DiscourseConnect-Anbieters
Um das Debugging von DiscourseConnect zu unterstützen, können Sie die Site-Einstellung verbose_discourse_connect_logging aktivieren. Durch Aktivieren dieser Einstellung werden ausführliche Diagnoseinformationen in IHRESITE.com/logs angezeigt. Stellen Sie sicher, dass Sie das Kästchen warnings am Ende von IHRESITE.com/logs
aktivieren.
Wir protokollieren eine Warnung in den Logs mit einem vollständigen Dump der SSO-Payload:
-
Jedes Mal, wenn der DiscourseConnect-Prozess gestartet wird, protokollieren wir eine Warnung im Log mit einem vollständigen Dump der DiscourseConnect-Payload.
-
Jedes Mal, wenn ein Benutzer den DiscourseConnect-Vorgang nicht abschließen kann (aufgrund abgelaufener Nonce oder IP-Sperre).
Müssen Sie Benutzeranmeldungen automatisieren? Siehe Auto-provisioning user accounts when SSO is enabled


