إضافة SSO بعد تسجيل العديد من المستخدمين بالفعل -- كيف يمكن ترحيلهم؟

مرحباً بالجميع.

ما هي الطريقة الصحيحة لاستيراد جميع مستخدمي Discourse الحاليين إلى intercoin.app من Discourse؟ هل هناك نوع من نقاط النهاية REST التي تُرجع جميع المستخدمين بكلمات المرور المجزأة والأملاح الخاصة بهم، من بين أشياء أخرى؟ ما هو الرابط الخاص بخوارزمية التجزئة على github؟ سأضطر إلى البرمجة من جانبنا، لاستخدام نفس خوارزمية التجزئة مع كلمة المرور المدخلة والملح، إذا لم تعمل خوارزميتنا الخاصة، للسماح لهؤلاء الأشخاص بتسجيل الدخول. أعتقد أن #2 ذو صلة كلما قام مستخدم Discourse بتشغيل تسجيل الدخول الأحادي لاحقًا (مثلما فعلنا) لذا فإن حله سيساعد مستخدمي Discourse الآخرين أيضًا.

إعجابَين (2)

نهج مثير للاهتمام.

في 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

ثم كود Pbkdf2 هنا: discourse/lib/pbkdf2.rb at 201228162c277b9833bb2988388553fdbfb39521 · discourse/discourse · GitHub

إعجابَين (2)

ممتاز! الآن ما هو نقطة النهاية HTTP التي يجب أن أتصل بها للحصول على جميع معلومات المستخدم، بما في ذلك تجزئة كلمة المرور والملح؟

أتخيل أنه لا يوجد واحد لتقديمه للجمهور (لماذا تسهيل اختراق الأشخاص؟) فماذا يمكنني أن أفعل؟ الاتصال بقاعدة بيانات MySQL؟ كتابة إضافة Discourse؟

إعجاب واحد (1)

هذه هي خياراتك الأساسية، نعم.

إعجاب واحد (1)

هل مخطط قاعدة البيانات موثق في أي مكان؟

كيف أتصل بقاعدة بيانات بوستجريس في دوكر؟ آسف إذا كان سؤالاً سخيفًا.

إعجاب واحد (1)

لقد تحدثت للتو مع فريقنا، وهم يوافقون، أنا مستعد لدفع لشخص ما لإنشاء إضافة صغيرة لـ Discourse تعرض عبر نقطة نهاية بعض معلومات JSON حول مستخدم، بالنظر إلى عنوان بريده الإلكتروني.

لقد وجدت discourse/app/models/user.rb at main · discourse/discourse · GitHub يحتوي على “password_hash” الملح والاسم واسم المستخدم. ولكنه لا يحتوي على البريد الإلكتروني. لذلك، أرى user_email discourse/app/models/user_email.rb at main · discourse/discourse · GitHub

لذلك، بالنظر إلى البريد الإلكتروني، ستبحث الإضافة ببساطة في جدول user_email حسب البريد، ثم تجد user_id وتحصل على صف المستخدم، وترسل جميع الحقول “الآمنة”، بما في ذلك الملح.

لمزيد من الأمان، يمكن توقيع الطلبات عبر HMAC باستخدام سر مشترك يمكن توفيره للإضافة.

هل يرغب أي شخص في القيام بهذا؟ راسلني أو رد هنا وأخبرني كيف يمكنني التواصل معك. نأمل أن يكون الأمر مباشرًا (بعض استعلامات SELECT وفحص HMAC إذا تم تعيين السر). سنقرأ JSON.

إعجاب واحد (1)

سأستخدم فقط admin/users/list/active.json الحالي وأوسع الاستجابة بكلمات المرور المجزأة.

أيضًا، التزم بآلية المصادقة الحالية لواجهة برمجة التطبيقات، ولا تخترع عجلة أخرى.

إعجاب واحد (1)

إذًا أنت تقول أن يكون لدي شيء لمرة واحدة يقوم باستيراد جميع المستخدمين المنضمين مع جميع أملاحهم وكلمات مرورهم؟

حسنًا، لكن هذا لا يزال بحاجة إلى أن يكون إضافة، أليس كذلك؟ لذا سيكون من الرائع لو قام شخص ما لديه خبرة في Discourse بإنشاء ذلك.

إعجاب واحد (1)

ربما سأستخدم إضافة مستكشف البيانات لتصدير المعلومات التي تريدها. سيكون الأمر أسهل بكثير من كتابة إضافة جديدة.

إعجاب واحد (1)

كيف يمكنني معرفة قيمة هذا الإعداد؟ ما هي القيمة الافتراضية، وهل هي موجودة في الكود في مكان ما؟ @RGJ

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

شكراً لك! حسناً @RGJ، لدي سؤالان سريعان:

مكتبة xorcist هي مجرد XOR أسرع للسلاسل النصية، صحيح؟ ماذا يحدث إذا انتهت إحدى الأحرف بـ 0 لأن ‘a’ تم عمل XOR لها مع ‘a’ - ماذا يحدث لتلك السلسلة؟ أليست السلاسل النصية منتهية بـ null؟

هدفي هو نقل هذا إلى PHP، لذا فإن أي شيء يمكنك فعله للمساعدة (مثل تزويدي بمعلومات حول كيفية تكراره في PHP) سيكون مفيدًا جدًا.

أيضًا، ماذا يفعل هذا السطر؟ 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: اكتشف ما يفعله RUBY في هذا السطر الأخير

هل هذا قريب؟ هل يمكنك من فضلك إصلاح كود PHP هذا؟

هذه دالة مدمجة.

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

عادةً ما تعمل خوارزميات التجزئة على البيانات الثنائية ويتم ترميز النتيجة بترميز سداسي عشري أو Base64 عند الإخراج. لذلك ليست هذه مشكلة.

إعجاب واحد (1)

شكرا جزيلا لك ريتشارد! لقد وفرت علي الكثير من الوقت في تنفيذها في بيئة PHP!

نعم! تمكنت من إنشاء نص برمجي يمر عبر جميع مستخدمي Discourse، ويقوم باستيرادهم مع تجزئة عبارة المرور الخاصة بهم إلى منصتنا.

قريبًا، سنتمكن من السماح لأي شخص لديه منتدى Discourse بإضافة الأحداث، ومؤتمرات الفيديو، والوسائط، والمزيد، مع بقاء Discourse في علامة التبويب “مناقشة”. يمكنك رؤية النتيجة على https://intercoin.app

بشكل أساسي، تحويل أي تثبيت Discourse إلى شبكة اجتماعية حديثة على غرار فيسبوك. لقد عملنا لسنوات على هذه الميزات والآن نريد دمجها بإحكام مع Discourse و Wordpress أيضًا. حتى يتمكن الأشخاص من الجمع بين Wordpress و Discourse و Qbix واستضافة مجتمعهم بالكامل بأنفسهم.

ولكن لدي مشكلتان متبقيتان.

  1. في Qbix، نقوم بتجزئة كلمة المرور على العميل على الأقل باستخدام sha1(password + userId) قبل إرسالها إلى الخادم. حتى عندما يكون https. نقوم بذلك حتى لا يمتلك الخادم أو أي MITM كلمة المرور أبدًا، لإعادة استخدامها عبر المواقع. ولكن، يرسل Discourse كلمة المرور ببساطة إلى الخادم. لذلك اضطررنا إلى إيقاف هذه التجزئة من جانب العميل. هل من الممكن إجراء بعض التكرارات من hash_pbkdf2 على جانب العميل، والباقي على جانب الخادم؟ لقد حاولت ويبدو أنها لا تتطابق:
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. هل سيكون من الممكن استخدام Discourse كمزود SSO، بدلاً من استخدام موقعنا كمزود SSO؟ عندها من المرجح أن يقوم مضيفو منتديات Discourse بتوسيعه بميزات Qbix، نظرًا لأن تسجيل الدخول سيظل كما هو تمامًا، وعلى جانب Discourse. فيسبوك، جوجل، وأي شيء آخر. هل هناك أي وثائق حول نوع المعلومات التي يعيدها Discourse Connect كمزود SSO إلى موقع المستهلك الخاص بنا؟ هل يشمل أشياء مثل الصورة التي يمكننا تنزيلها، والاسم الأول، والاسم الأخير، واسم المستخدم على الأقل؟

بصراحة، لا أعتقد أن إرسال كلمة مرور عبر HTTPS يمثل أكبر تحدٍ أمني لديك في الوقت الحالي.

بالتأكيد. أعتقد أنك تحصل على معظم الأشياء في مُسلسِل المستخدم القياسي.
ولكن إذا لم يكن ذلك كافيًا، يمكنك دائمًا استخدام واجهة برمجة التطبيقات (API) للحصول على مزيد من المعلومات من Discourse.

إعجابَين (2)

\u003e بصراحة، لا أعتقد أن إرسال كلمة مرور عبر HTTPS يمثل أكبر تحدٍ أمني لديك في الوقت الحالي.\n\nلطيف. أرى الـ sha1 الخاص بك وأخفضه إلى md5 :slight_smile: \nhttps://news.ycombinator.com/item?id=32796841\n\nأرى لماذا لا يعمل pbkdf2 حقًا لتقسيمه… المشكلة هي السطر الأول:\n\n\n\nU1 = PRF(Password, Salt + INT_32_BE(i))\nU2 = PRF(Password, U1)\n⋮\nUc = PRF(Password, Uc−1)\n\n\nهل لديك أي أفكار حول كيفية تقسيمه، مع ذلك؟ أعتقد أنه يمكنني فقط استخدام مكتبة php النقية: https://github.com/Spomky-Labs/pbkdf2/blob/master/src/PBKDF2.php\n\nأود أن أوصي Discourse بتجزئة الأشياء باستخدام ملح (معرف المستخدم يعمل) قبل إرسال كلمة المرور عبر الشبكة. لماذا لا؟ لا يجب أن تصبح غير متوافقة مع ما تخزنه في قاعدة البيانات الآن. ببساطة قم بأول 100 تكرار في Javascript، ثم اطرح 10 من 64000. لديك تطبيق مخصص له على أي حال (منسوخ من rails) لذا سترسل ببساطة متغير isHashed، وإذا كان صحيحًا، فقم فقط بـ "آخر" 64K-10 خطوات.

معرف المستخدم غير معروف قبل تسجيل الدخول لذلك لن ينجح هذا…

10 تكرارات ليست آمنة، و 63990 تكرارًا أقل أمانًا من 64000 تكرار. لذلك، على الرغم من أنها هامشية، يبدو أنك تستبدل طريقة آمنة بطريقتين أقل أمانًا والكثير من التعقيد الإضافي.

وما هو المكسب الفعلي؟

إعجاب واحد (1)