يُعد DiscourseConnect ميزة أساسية في Discourse تتيح لك تكوين “تسجيل الدخول الموحد (SSO)” لتفويض جميع عمليات تسجيل الدخول وتسجيل المستخدمين من Discourse بالكامل إلى موقع آخر. متوفر لعملائنا في خطط الاستضافة الاحترافية، التجارية، والمؤسسية.
(فبراير 2021) تم تغيير اسم “Discourse SSO” إلى “DiscourseConnect”. إذا كنت تشغل إصدارًا قديمًا من Discourse، فستُسمى الإعدادات أدناه
sso_...بدلاً منdiscourse_connect_...
المشكلة
تود العديد من المواقع التي ترغب في التكامل مع موقع Discourse الاحتفاظ بجميع عمليات تسجيل المستخدمين في موقع منفصل. في مثل هذا الإعداد، يجب تفويض جميع عمليات تسجيل الدخول إلى ذلك الموقع الآخر.
ماذا لو أردت استخدام SSO بالتزامن مع مصادقة موجودة؟
الهدف من DiscourseConnect هو استبدال مصادقة Discourse. إذا كنت ترغب في إضافة مزود جديد، فراجع الإضافات الموجودة مثل: Discourse VK Authentication (vkontakte)
تمكين DiscourseConnect
لتمكين DiscourseConnect، يجب عليك ملء ثلاث إعدادات:
enable_discourse_connect: يجب تمكينه، وهو مفتاح عام.
discourse_connect_url: عنوان URL خارجي سيتم توجيه المستخدمين إليه عند محاولة تسجيل الدخول.
discourse_connect_secret: سلسلة سرية تُستخدم لتجزئة حمولات SSO. تضمن أصالة الحمولات.
بمجرد تعيين enable_discourse_connect إلى true:
- عند النقر على تسجيل الدخول أو الصورة الرمزية، سيتم إعادة توجيهك إلى
/session/sso، والذي بدوره سيعيد توجيه المستخدمين إلىdiscourse_connect_urlمع حمولة موقعة. - لن يُسمح للمستخدمين بـ “تغيير كلمة المرور”. يتم إزالة هذا الحقل من ملف المستخدم.
- لن يتمكن المستخدمون بعد الآن من استخدام مصادقة Discourse (اسم المستخدم/كلمة المرور، Google، إلخ).
ماذا لو قمت بتفعيله بالخطأ؟
راجع: Log back in as admin after locking yourself out with read-only mode or an invalid SSO configuration
تنفيذ DiscourseConnect على موقعك
يستخدم Discourse عناوين البريد الإلكتروني لربط المستخدمين الخارجيين بمستخدمي Discourse، ويفترض أن عناوين البريد الإلكتروني الخارجية آمنة. إِذَا لَمْ تُعَزِّزَ صِحَّةَ عَوَازِلِ الْبَرِيدِ الْإِلِكْتُرُونِيِّ قَبْلَ إِرسالِهَا إِلَى DISCOURSE، فَموقعُكَ سَيَكُونُ شَدِيدَ الضَّعْفِ!
بدلاً من ذلك، إذا كنت مصراً على إرسال عناوين بريد إلكتروني غير معززة، تأكد من تعيين require_activation=true. هذا سيجبر جميع عناوين البريد الإلكتروني على التحقق من صحتها بواسطة Discourse. نُنصح بشدة بعدم القيام بذلك، لذا إذا واصلت معتمدين على هذا الإعداد، فإنك تتحمل مخاطر كبيرة.
سيقوم Discourse بإعادة توجيه العملاء إلى discourse_connect_url مع حمولة موقعة: (لنفترض أن discourse_connect_url هو https://somesite.com/sso)
ستستقبل حركة مرور واردة على النحو التالي:
https://somesite.com/sso?sso=PAYLOAD&sig=SIG
الحمولة هي سلسلة مشفرة بـ Base64 تتكون من nonce و return_sso_url. الحمولة هي دائمًا سلسلة استعلام صالحة.
على سبيل المثال، إذا كان الـ nonce هو ABCD، فسيكون raw_payload كالتالي:
nonce=ABCD&return_sso_url=https%3A%2F%2Fdiscourse_site%2Fsession%2Fsso_login، ويتم تشفير هذه الحمولة الخام بـ base 64.
يجب أن يقوم نقطة النهاية المستدعاة بما يلي:
- التحقق من صحة التوقيع: تأكد من أن HMAC-SHA256 الخاص بـ
PAYLOAD(باستخدامdiscourse_connect_secretكمفتاح) يساويsig(سيكونsigمشفرًا بصيغة سداسية عشرية). - تنفيذ أي مصادقة مطلوبة.
- إنشاء حمولة جديدة مشفرة بـ URL تحتوي على الأقل على nonce و email و external_id. يمكنك أيضًا تقديم بعض البيانات الإضافية، إليك قائمة بجميع المفاتيح التي سيفهمها Discourse:
- يجب نسخ nonce من حمولة الإدخال.
- يجب أن يكون email عنوان بريد إلكتروني معتمدًا. إذا لم يتم التحقق من عنوان البريد الإلكتروني، فقم بتعيين require_activation إلى “true”.
- external_id هو أي سلسلة فريدة للمستخدم لن تتغير أبدًا، حتى لو تغير بريدُه الإلكتروني أو اسمه أو غيره. القيمة المقترحة هي رقم الصف ‘id’ في قاعدة بياناتك.
- سيصبح username اسم المستخدم في Discourse إذا كان المستخدم جديدًا أو إذا تم تعيين
SiteSetting.auth_overrides_username. - سيصبح name الاسم الكامل في Discourse إذا كان المستخدم جديدًا أو إذا تم تعيين
SiteSetting.auth_overrides_name. - سيتم تحميل avatar_url وتعيينه كصورة رمزية للمستخدم إذا كان المستخدم جديدًا أو إذا تم تعيين
SiteSetting.discourse_connect_overrides_avatar. - avatar_force_update هو حقل منطقي (boolean). إذا تم تعيينه إلى true، فسيفرض على Discourse تحديث الصورة الرمزية للمستخدم، سواء تغيرت
avatar_urlأم لا. - سيصبح bio محتوى السيرة الذاتية للمستخدم إذا كان المستخدم جديدًا، أو كانت سيرته الذاتية فارغة، أو تم تعيين
SiteSetting.discourse_connect_overrides_bio. - سيُعد title لقب المستخدم.
- سيُعد website موقع المستخدم في ملفه الشخصي.
- سيُعد location موقع المستخدم في ملفه الشخصي.
- سيتم تحميل profile_background_url وتعيينه كخلفية ملف المستخدم إذا كان المستخدم جديدًا أو إذا تم تعيين
SiteSetting.discourse_connect_overrides_profile_background. - سيتم تحميل card_background_url وتعيينه كخلفية بطاقة المستخدم إذا كان المستخدم جديدًا أو إذا تم تعيين
SiteSetting.discourse_connect_overrides_card_background. - سيُعد locale لغة المستخدم إذا كان المستخدم جديدًا وتم تمكين
SiteSetting.allow_user_locale. - locale_force_update هو حقل منطقي. إذا تم تعيينه إلى true مع locale، فسيُجبر على تحديث اللغة للمستخدمين الحاليين (يتطلب
SiteSetting.allow_user_locale). - الحقول المنطقية الإضافية (“true” أو “false”) هي: admin، moderator، suppress_welcome_message، logout.
- قم بتشفير الحمولة بـ Base64.
- احسب تجزئة HMAC-SHA256 للحمولة باستخدام
discourse_connect_secretكمفتاح والحمولة المشفرة بـ Base64 كنص. - أعد التوجيه إلى
return_sso_urlمع معلمتي استعلامssoوsig(http://discourse_site/session/sso_login?sso=payload&sig=sig).
سيقوم Discourse بالتحقق من صحة الـ nonce، وإذا كان صالحًا، فسيستنفده فورًا حتى لا يمكن استخدامه مرة أخرى. ثم سيحاول:
- تسجيل دخول المستخدم عن طريق البحث عن external_id مرتبط بالفعل في نموذج
SingleSignOnRecord. - تسجيل دخول المستخدم باستخدام البريد الإلكتروني المقدم (تحديث external_id) (ما لم يكن require_activation = true).
- إنشاء حساب جديد للمستخدم مع تقديم (البريد الإلكتروني، اسم المستخدم، الاسم) وتحديث external_id.
مخاوف أمنية
سيستنفد الـ nonce (الرمز لمرة واحدة) تلقائيًا بعد 30 دقيقة. هذا يعني أنه بمجرد إعادة توجيه المستخدم إلى موقعك، يكون لديه 30 دقيقة لتسجيل الدخول أو إنشاء حساب جديد.
البروتوكول آمن ضد هجمات إعادة التشغيل لأن الـ nonce يمكن استخدامه مرة واحدة فقط. يرتبط الـ nonce بجلسة المتصفح الحالية للحماية من هجمات CSRF.
تحديد عضوية المجموعات
إذا تم تحديد خيار discourse connect overrides groups، فسينظر Discourse في القائمة المفصولة بفواصل للمجموعات الممررة في groups.
بالإضافة إلى groups، يمكنك أيضًا تحديد عضوية المجموعات في حمولة SSO الخاصة بك باستخدام سمات add_groups و remove_groups بغض النظر عن خيار discourse connect overrides groups.
add_groups هي قائمة مفصولة بفواصل لأسماء المجموعات التي سنضمن أن المستخدم عضو فيها.
remove_groups هي قائمة مفصولة بفواصل لأسماء المجموعات التي سنضمن أن المستخدم ليس عضوًا فيها.
تنفيذ مرجعي
يحتوي Discourse على تنفيذ مرجعي لفئة SSO:
سيكون التنفيذ التافه كالتالي:
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" # معرف فريد لكل مستخدم في تطبيقك
sso.sso_secret = secret
redirect_to sso.to_url("http://l.discourse/session/sso_login")
end
end
الانتقال إلى تسجيل الدخول الموحد منه.
طالما لم يتم تعيين معامل require_activation إلى true في حمولة الطلب، فإن النظام يثق في عناوين البريد الإلكتروني المقدمة من نقطة نهاية تسجيل الدخول الموحد. هذا يعني أنه إذا كان لديك حساب موجود سابقًا في Discourse مع تعطيل DiscourseConnect، فسيقوم DiscourseConnect بإعادة استخدامه ببساطة وتجنب إنشاء حساب جديد.
إذا قمت بإيقاف تشغيل DiscourseConnect، فسيتمكن المستخدمون من إعادة تعيين كلمات المرور والحصول على الوصول إلى حساباتهم مرة أخرى.
مثال من العالم الحقيقي:
بافتراض الإعدادات التالية:
نطاق Discourse: http://discuss.example.com
عنوان URL الخاص بـ DiscourseConnect: http://www.example.com/discourse/sso
سر DiscourseConnect: d836444a9e4084d5b224a60c208dce14
تم التحقق من البريد الإلكتروني: لا (أضف require_activation=true إلى الحمولة)
محاولة مستخدم لتسجيل الدخول
-
يتم إنشاء الـ nonce:
cb68251eefb5211e58c00ff1395f0c0b -
يتم إنشاء الحمولة الخام:
nonce=cb68251eefb5211e58c00ff1395f0c0b -
يتم تشفير الحمولة بـ Base64:
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI= -
يتم تشفير الحمولة بـ URL:
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI%3D -
يتم إنشاء HMAC-SHA256 على الحمولة المشفرة بـ Base64:
1ce1494f94484b6f6a092be9b15ccc1cdafb1f8460a3838fbb0e0883c4390471
أخيرًا، يتم إعادة توجيه المتصفح إلى:
http://www.example.com/discourse/sso?sso=bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI%3D&sig=1ce1494f94484b6f6a092be9b15ccc1cdafb1f8460a3838fbb0e0883c4390471
في الطرف الآخر
- يتم التحقق من الحمولة باستخدام HMAC-SHA256، إذا لم يتطابق التوقيع، تتوقف العملية.
- عن طريق عكس الخطوات المذكورة أعلاه، يتم استخراج الـ nonce.
تسجيل دخول المستخدم:
name: sam
external_id: hello123
email: test@test.com
username: samsam
require_activation: true
يتم إنشاء حمولة غير موقعة:
nonce=cb68251eefb5211e58c00ff1395f0c0b&name=sam&username=samsam&email=test%40test.com&external_id=hello123&require_activation=true
الترتيب لا يهم، القيم مشفرة بـ URL
يتم تشفير الحمولة بـ Base64
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGImbmFtZT1zYW0mdXNlcm5hbWU9c2Ftc2FtJmVtYWlsPXRlc3QlNDB0ZXN0LmNvbSZleHRlcm5hbF9pZD1oZWxsbzEyMyZyZXF1aXJlX2FjdGl2YXRpb249dHJ1ZQ==
يتم تشفير الحمولة بـ URL
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGImbmFtZT1zYW0mdXNlcm5hbWU9c2Ftc2FtJmVtYWlsPXRlc3QlNDB0ZXN0LmNvbSZleHRlcm5hbF9pZD1oZWxsbzEyMyZyZXF1aXJlX2FjdGl2YXRpb249dHJ1ZQ%3D%3D
يتم توقيع الحمولة المشفرة بـ Base64
3d7e5ac755a87ae3ccf90272644ed2207984db03cf020377c8b92ff51be3abc3
يعيد المتصفح التوجيه إلى:
http://discuss.example.com/session/sso_login?sso=bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGImbmFtZT1zYW0mdXNlcm5hbWU9c2Ftc2FtJmVtYWlsPXRlc3QlNDB0ZXN0LmNvbSZleHRlcm5hbF9pZD1oZWxsbzEyMyZyZXF1aXJlX2FjdGl2YXRpb249dHJ1ZQ%3D%3D&sig=3d7e5ac755a87ae3ccf90272644ed2207984db03cf020377c8b92ff51be3abc3
مزامنة سجلات DiscourseConnect
يمكنك استخدام نقطة نهاية الإدارة POST /admin/users/sync_sso لمزامنة سجل DiscourseConnect، وتمرير نفس السجل الذي ستمرره إلى نقطة نهاية DiscourseConnect، ولا يهم الـ nonce.
إذا قمت باستدعاء admin/users/sync_sso من موقع آخر، فستحتاج إلى تضمين api_key إداري صالح و api_username صالح في رؤوس الطلب. راجع Sync DiscourseConnect user data with the sync_sso route لمزيد من التفاصيل حول كيفية هيكلة الطلب.
مسح سجلات DiscourseConnect
إذا تغيرت قيم external_id الخاصة بك من مزود DiscourseConnect (ربما قمت بتغيير خوارزمية التوليد، أو ربما هي نقطة نهاية مختلفة)، فيمكنك إزالة جميع السجلات الموجودة بأمان باستخدام وحدة تحكم rails:
SingleSignOnRecord.destroy_all
تسجيل خروج المستخدمين
يمكنك استخدام نقطة نهاية الإدارة POST /admin/users/{USER_ID}/log_out لتسجيل خروج أي مستخدم في النظام عند الحاجة.
لتكوين نقطة النهاية التي يعيد توجيه Discourse إليها عند تسجيل الخروج، ابحث عن إعداد logout redirect. إذا لم يتم تعيين أي عنوان URL هنا، فسيتم إعادة توجيهك إلى العنوان المكون في discourse connect url.
البحث عن المستخدمين حسب external_id
يمكن الوصول إلى بيانات ملف المستخدم باستخدام نقطة النهاية /users/by-external/{EXTERNAL_ID}.json. سيعيد هذا حمولة JSON تحتوي على معلومات المستخدم، بما في ذلك user_id الذي يمكن استخدامه مع نقطة نهاية log_out.
تنفيذات موجودة
-
يمكن استخدام مكتبة
discourse_apiلـ SSO. راجع كود SSO في مجلد الأمثلة لرؤية تنفيذ أساسي. -
يجعل إضافة WordPress الخاصة بنا من السهل تكوين SSO بين WordPress و Discourse. توجد تفاصيل حول إعداده في علامة التبويب SSO في صفحة خيارات الإضافة.
عمل مستقبلي
- نود جمع المزيد من التنفيذات المرجعية لـ SSO على منصات أخرى. إذا كان لديك واحد، فيرجى النشر في فئة Dev / SSO.
ميزات متقدمة
- يمكنك تمرير حقول مخصصة للمستخدمين عن طريق إضافة بادئة
customلاسم الحقل. على سبيل المثال، يمكن استخدامcustom.user_field_1لتعيين قيمةUserCustomFieldالتي تحمل الاسمuser_field_1. - يمكنك تمرير
avatar_urlلتجاوز الصورة الرمزية للمستخدم (يجب تمكينSiteSetting.discourse_connect_overrides_avatar). يتم تخزين الصور الرمزية مؤقتًا، لذا مررavatar_force_update=trueلإجبارها على التحديث إذا كان العنوان هو نفسه. حاليًا، لا يمكنك تمرير عنوان URL فارغ لتعطيل صورة المستخدم الرمزية. - بشكل افتراضي، سيتم إرسال رسالة الترحيب إلى جميع المستخدمين الجدد المُنشأين عبر SSO. إذا كنت ترغب في قمع ذلك، فيمكنك تمرير
suppress_welcome_message=true. - لتكوين مثيل Discourse الخاص بك كمزود Discourse Connect، راجع: استخدام DiscourseConnect كمزود هوية.
تصحيح مشكلة مزود DiscourseConnect الخاص بك
لمساعدة في تصحيح مشكلة DiscourseConnect، يمكنك تمكين إعداد الموقع verbose_discourse_connect_logging. بتمكين هذا الإعداد، ستظهر تشخيصات غنية في YOURSITE.com/logs. تأكد من تحديد مربع
warnings في أسفل YOURSITE.com/logs.
سنسجل تحذيرًا في السجلات مع تصدير كامل لحمولة SSO:
-
في كل مرة يتم فيها بدء عملية DiscourseConnect، سنسجل تحذيرًا في السجل مع تصدير كامل لحمولة DiscourseConnect.
-
في كل مرة يفشل فيها المستخدم في إكمال DiscourseConnect (بسبب انتهاء صلاحية الـ nonce أو حظر عنوان IP).
هل تحتاج إلى أتمتة تسجيلات المستخدمين؟ راجع Auto-provisioning user accounts when SSO is enabled


