SSO hinzufügen, nachdem sich bereits viele Benutzer angemeldet haben -- wie migriert man sie?

Hallo zusammen.

Wie importiere ich am besten alle bestehenden Discourse-Benutzer nach intercoin.app von Discourse? Gibt es eine Art REST-Endpunkt, der alle Benutzer mit ihren gehashten Passwörtern und Salts zurückgibt, unter anderem? Wie lautet der Link zum Hash-Algorithmus auf GitHub? Ich muss auf unserer Seite den gleichen Hash-Algorithmus mit dem eingegebenen Passwort und Salt verwenden, falls unser eigener nicht funktioniert, um diesen Leuten die Anmeldung zu ermöglichen. Ich denke, #2 ist relevant, wenn ein Discourse-Benutzer später SSO aktiviert (wie wir es tun), daher würde die Lösung dieses Problems auch anderen Discourse-Benutzern helfen.

2 „Gefällt mir“

Interessanter Ansatz.

In user.rb

  def confirm_password?(password)
    return false unless password_hash && salt
    self.password_hash == hash_password(password, salt)
  end

  def hash_password(password, salt)
    raise StandardError.new("password is too long") if password.size > User.max_password_length
    Pbkdf2.hash_password(password, salt, Rails.configuration.pbkdf2_iterations, Rails.configuration.pbkdf2_algorithm)
  end

und dann ist der Pbkdf2-Code hier: discourse/lib/pbkdf2.rb at 201228162c277b9833bb2988388553fdbfb39521 · discourse/discourse · GitHub

2 „Gefällt mir“

Ausgezeichnet! Nun, welcher HTTP-Endpunkt muss ich aufrufen, um alle Benutzerinformationen, einschließlich des Passwort-Hashes und des Salts, zu erhalten?

Ich stelle mir vor, dass es keinen gibt, der für die breite Öffentlichkeit zugänglich ist (warum sollte es einfacher sein, Leute zu hacken?). Was kann ich also tun? Die MySQL-Datenbank verbinden? Ein Discourse-Plugin schreiben?

1 „Gefällt mir“

Das sind im Grunde Ihre Optionen, ja.

1 „Gefällt mir“

Ist das Datenbankschema irgendwo dokumentiert?

Wie verbinde ich mich mit der Postgres-Datenbank in Docker? Entschuldigung, wenn es eine dumme Frage ist.

1 „Gefällt mir“

Ich habe gerade mit unserem Team gesprochen, und sie stimmen zu, ich bin bereit, jemanden dafür zu bezahlen, ein kleines Discourse-Plugin zu erstellen, das über einen Endpunkt einige JSON-Infos über einen Benutzer preisgibt, gegeben seine E-Mail-Adresse.

Ich habe festgestellt, dass https://github.com/discourse/discourse/blob/main/app/models/user.rb#L1855 “password_hash” Salt und Name, Benutzername hat. Aber es hat keine E-Mail. Dafür sehe ich user_email discourse/app/models/user_email.rb at main · discourse/discourse · GitHub

Also, gegeben eine E-Mail, wird das Plugin einfach die user_email-Tabelle nach der E-Mail durchsuchen, dann die user_id finden und die Benutzerzeile abrufen und alle “sicheren” Felder senden, einschließlich des Salts.

Für zusätzliche Sicherheit können die Anfragen über HMAC mit einem gemeinsam genutzten Geheimnis signiert werden, das dem Plugin zur Verfügung gestellt werden kann.

Möchte das jemand machen? Schicken Sie mir eine Nachricht oder antworten Sie hier und lassen Sie mich wissen, wie ich Sie kontaktieren kann. Hoffentlich ist es unkompliziert (ein paar SELECTs und eine Prüfung auf HMAC, wenn das Geheimnis gesetzt wurde). Wir werden das JSON lesen.

1 „Gefällt mir“

Ich würde einfach die vorhandene admin/users/list/active.json verwenden und die Antwort um die gehashten Passwörter erweitern.

Verwenden Sie außerdem weiterhin den vorhandenen API-Authentifizierungsmechanismus, erfinden Sie kein Rad neu.

1 „Gefällt mir“

Sie sagen also, ich soll eine einmalige Sache haben, die alle beigetretenen Benutzer mit all ihren Salts und Passwörtern importiert?

In Ordnung, aber das muss immer noch ein Plugin sein, oder? Es wäre also großartig, wenn jemand von Discourse das erstellen könnte.

1 „Gefällt mir“

Ich würde wahrscheinlich das Data Explorer Plugin verwenden, um die gewünschten Informationen zu exportieren. Das ist viel einfacher, als ein neues Plugin zu schreiben.

1 „Gefällt mir“

Wie finde ich diesen Konfigurationswert heraus? Was ist der Standardwert, steht er irgendwo im Code? @RGJ

root@server:~# cd /var/discourse/
root@server:/var/discourse# ./launcher enter app
x86_64 arch erkannt.
root@server:/var/www/discourse# rails c
[1] pry(main)> Rails.configuration.pbkdf2_iterations
=> 64000
[2] pry(main)>

Danke! OK @RGJ ein paar schnelle Fragen:

Die xorcist-Bibliothek ist nur ein schnellerer String-XOR, richtig? Was passiert, wenn eines der Zeichen 0 wird, weil ‘a’ mit ‘a’ XORed wurde? Sind Strings nicht nullterminiert?

Mein Ziel ist es, dies nach PHP zu portieren. Alles, was Sie tun können, um mir zu helfen (wie z. B. Informationen zur Replikation in PHP), wird sehr hilfreich sein.

Was macht diese Zeile? ret.bytes.map { |b| ("0" + b.to_s(16))[-2..-1] }.join("")

$u = hash_hmac('sha256', $password, $salt . pack('N', 1));
$ret = $u = hash_hmac('sha256', $password, $u);
for ($i=2; $i<$iterations; ++$i) {
  $u = hash_hmac('sha256', $password, $u);
  $ret = ($ret ^ $u);
}
// todo: herausfinden, was RUBY in dieser letzten Zeile tut

Ist das ungefähr richtig? Können Sie diesen PHP-Code bitte korrigieren?

Dies ist eine eingebaute Funktion.

$hash = hash_pbkdf2('sha256', 'YourPassword', 'YourSalt', 64000, 64, false);

Normalerweise arbeiten Hash-Algorithmen mit Binärdaten und das Ergebnis wird bei der Ausgabe hexadezimal oder Base64-kodiert. Das ist also kein Problem.

1 „Gefällt mir“

Vielen Dank, Richard! Sie haben mir SO viel Zeit gespart, die ich sonst für die Implementierung in Userland-PHP aufwenden müsste!

Ja! Ich konnte ein Skript erstellen, das alle Discourse-Benutzer durchläuft und sie mit ihrem Passphrase-Hash auf unserer Plattform importiert.

Bald können wir jedem, der ein Discourse-Forum hat, auch Events, Videokonferenzen, Medien und mehr anbieten, wobei Discourse im Tab „Diskutieren“ angesiedelt ist. Das Ergebnis sehen Sie unter https://intercoin.app

Im Grunde verwandelt dies jede Discourse-Installation in ein modernes soziales Netzwerk à la Facebook. Wir haben jahrelang an diesen Funktionen gearbeitet und möchten sie nun eng in Discourse und WordPress integrieren. So können Leute WordPress, Discourse und Qbix kombinieren und ihre gesamte Community selbst hosten.

Aber es bleiben zwei Probleme.

  1. In Qbix hashen wir das Passwort auf dem Client, zumindest mit sha1(password + userId), bevor wir es an den Server senden. Selbst wenn es https ist. Wir tun dies, damit der Server oder ein MITM das Passwort NIEMALS hat, um es seitenübergreifend wiederzuverwenden. Aber Discourse sendet das Passwort einfach an den Server. Daher mussten wir dieses Hashing auf der Clientseite deaktivieren. Ist es möglich, einige Iterationen von hash_pbkdf2 auf der Clientseite und den Rest auf der Serverseite durchzuführen? Ich habe es versucht und es scheint nicht zu passen:
php > $password = 'abc';
php > $salt = 'def';
php > $a = hash_pbkdf2('sha256', $password, $salt, 64000, 64, false);
php > $b = hash_pbkdf2('sha256', $password, $salt, 1, 64, false);
php > $c = hash_pbkdf2('sha256', $password, $b, 63999, 64, false);
php > echo $a;
9d7a21ae4113bea06d81e0c486f45ab778bb739f19f7a6a305d8401918a9d8a1
php > echo $c;
f42af6861ebcf8560b027276e0d02ad46502636045486057d81be7c4c4aa630e
  1. Wäre es möglich, Discourse einfach als SSO-Provider zu verwenden, anstatt unsere Website als SSO-Provider zu verwenden? Dann würden die Hoster von Discourse-Foren es mit größerer Wahrscheinlichkeit mit Qbix-Funktionen erweitern, da die Anmeldung genau gleich bleiben würde und auf der Seite von Discourse. Facebook, Google und was auch immer sonst. Gibt es Dokumentationen darüber, welche Informationen Discourse Connect als SSO-Provider an unsere Consumer-Website zurückgibt? Enthält es Dinge wie das Foto, das wir herunterladen können, Vorname, Nachname und zumindest den Benutzernamen?

Ehrlich gesagt, glaube ich nicht, dass das Übertragen eines Passworts über HTTPS Ihre größte Sicherheitsproblem im Moment ist.

Sicher. Ich denke, Sie bekommen die meisten Dinge im Standard-Benutzer-Serializer.
Aber wenn das nicht ausreicht, können Sie die API immer verwenden, um weitere Informationen von Discourse abzurufen.

2 „Gefällt mir“

„Ehrlich gesagt, ich glaube nicht, dass die Übermittlung eines Passworts über HTTPS durch Discourse im Moment Ihre größte Sicherheitsherausforderung darstellt.“

Niedlich. Ich sehe Ihr sha1 und unterbiete Sie mit md5 :slight_smile:

Ich verstehe, warum pbkdf2 nicht wirklich funktioniert, um es aufzuteilen … das Problem ist die erste Zeile:

U1 = PRF(Password, Salt + INT_32_BE(i))
U2 = PRF(Password, U1)
⋮
Uc = PRF(Password, Uc−1)

Irgendwelche Ideen, wie man es aufteilen könnte? Ich schätze, ich kann einfach die reine Userland-PHP-Bibliothek verwenden: pbkdf2/src/PBKDF2.php at master · Spomky-Labs/pbkdf2 · GitHub

Ich würde Discourse empfehlen, Dinge mit einem Salt (userId funktioniert) zu hashen, bevor das Passwort über das Netz gesendet wird. Warum nicht? Es muss nicht inkompatibel mit dem werden, was Sie jetzt in der Datenbank speichern. Führen Sie einfach die ersten 100 Iterationen in Javascript durch, ziehen Sie dann 10 von 64000 ab. Sie haben sowieso eine benutzerdefinierte Implementierung davon (kopiert von Rails), also würden Sie einfach eine Variable isHashed mitsenden, und wenn sie true ist, führen Sie nur die „letzten“ 64K-10 Schritte durch.

Die Benutzer-ID ist vor dem Login nicht bekannt, daher funktioniert das nicht…

10 Iterationen sind nicht sicher, und 63990 Iterationen sind weniger sicher als 64000 Iterationen. Obwohl es geringfügig ist, scheint es, als würden Sie eine sichere Methode durch zwei weniger sichere Methoden und viel zusätzliche Komplexität ersetzen.

Und was ist der tatsächliche Gewinn?

1 „Gefällt mir“