استخدام Discourse كمزود هوية (SSO، DiscourseConnect)

مرحبًا :waving_hand:، لقد قمت بكتابة وحدة مصادقة SimpleSAMLphp هذه لتمكين استخدام Discourse كمزود SSO ضمن تثبيت SimpleSAMLphp. أي أنه يمكنك استخدام Discourse كمزود SSO لأي خدمات تدعم مصادقة SAML أو Shibboleth، وهو أمر رائع حقًا.

أخبرني برأيك (إذا كنت مهتمًا بالتعليق على الكود، يمكنك استخدام مشكلات GitHub).

4 إعجابات

هذا رائع! إذا كنت ترغب في جعل الوحدة أكثر وضوحًا، يمكنك إنشاء موضوع عنها في فئة #plugin:extras الخاصة بنا. هذه الفئة هي دليل لجميع الإضافات والتكاملات لـ Discourse التي ليست إضافات Discourse نفسها،

3 إعجابات

تعديل: تمت إضافة صورة نموذج أولي


أنا أقوم بتطبيق نظام تسجيل الدخول الموحد (SSO) هذا على موقع ويب موجود، وأود فقط التحقق من كيفية “عرض” طريقة تسجيل الدخول للمستخدمين.

على سبيل المثال، لنفترض أن موقعي الإلكتروني على www.example.com يحتوي على زر “تسجيل الدخول” في شريط التنقل العلوي.

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

أتساءل فقط عما إذا كان المستخدمون سيشعرون بالارتباك إذا لم يُخبروا بما هو قادم؟ :thinking:

هل لدى أي شخص أي تجارب مستخدم أو ممارسات مثالية للمشاركة؟

وشكرًا أيضًا لـ @techAPJ على المنشور الأول المفصل جدًا في هذا الموضوع، لقد تمكنت بنجاح من دمج هذا في موقعي الإلكتروني المبنى بـ ASP.NET من الصفر باتباع خطواتك :+1:t2:

إعجابَين (2)

هل من الممكن تضمين معلمة حالة تُعاد دون تغيير، كما يُفعل في OAuth؟ يعتمد وسيط المصادقة في Asp.net core على إنشاء معرف ارتباط لمنع هجمات CSRF، ولا أملك حاليًا طريقة سهلة لتضمينه.

ألا يمكنك إضافته إلى سلسلة الاستعلام في عنوان URL الخاص بـ callback قبل تغليفه؟

على سبيل المثال:

nonce=NONCE&return_sso_url=https://www.example.com/my/callback_url.aspx?myparam=here

@jessicah جربت هذا اليوم ونعم، يعمل بشكل صحيح.

        ' إنشاء عنوان URL للإرجاع
        Dim strReturnURL As String = "https://www.example.com/authtestRETURNURL.aspx?myownparametershere=surewhynot"

        ' إنشاء رمز غير مستخدم عشوائي. احفظه مؤقتًا حتى تتمكن من التحقق منه مع قيمة الرمز غير المستخدم المُرجعة
        Dim strNonce As String = Guid.NewGuid().ToString("N")

        ' إنشاء حمولة جديدة تحتوي على الرمز غير المستخدم وعنوان URL للإرجاع (حيث سيعيد Discourse توجيه المستخدم بعد التحقق)
        '       يجب أن تبدو الحمولة كالتالي: nonce=NONCE&return_sso_url=RETURN_URL
        Dim strPayload As String = "nonce=" & strNonce & "&return_sso_url=" & strReturnURL

ثم في الصفحة التي يتم استدعاؤها مرة أخرى، ستجد هذا داخل سلسلة استعلام SSO المفككة:

&return_sso_url=http%3A%2F%2Fwww.example.com%2FauthtestRETURNURL.aspx%3Fmyownparametershere%3Dsurewhynot&username=Rich

نأمل أن هذا هو ما تقصده؟

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

نهج متعددة المواقع لاستخدام discourse-auth-proxy؟

هل توجد أمثلة أو توصيات لاستخدام Discourse كمزود لتسجيل الدخول الموحد (SSO) للمصادقة عبر مواقع متعددة؟

يبدو أن هناك طريقتين أساسيتين للعمل مع مواقع متعددة:

  1. استخدام عدة نسخ من discourse-auth-proxy، نسخة واحدة لكل موقع محمي.
  2. استخدام نسخة واحدة من discourse-auth-proxy بحيث يتغير الحمولة (payload) التي تحتوي على return_sso_url بناءً على مصدر طلب تسجيل الدخول.

أعتقد أن أيًا من هاتين الطريقتين يمكن أن ينجح، لكن المشكلة فيهما هي أنك لا تزال بحاجة إلى تسجيل الدخول إلى كل موقع مختلف.
هناك أيضًا خطر أن يتم تخزين شيء ما في Postgres سيتم استبداله عند كل تسجيل دخول من المواقع المختلفة. أي: site1.com، site2.com
(لا أعرف تفاصيل مخطط مصادقة Discourse أو قاعدة بيانات PostgreSQL، لذا لا أستطيع الجزم).

المثالي هو وجود طريقة لإجراء تسجيل الدخول مرة واحدة، مما يتيح لك الدخول إلى جميع المواقع ضمن مجموعة المواقع المتعددة. أي: site1.com، site2.com، site3.com

يبدو أن Stackoverflow تفعل ذلك باستخدام مزيج من التخزين المحلي (localSession) وإطارات الويب (Iframes) كآلية رئيسية. الوصف التقني

لكنني أود حقًا معرفة ما إذا كان شخص ما قد طبق أي نهج لتسجيل الدخول عبر مواقع متعددة باستخدام Discourse كمزود لتسجيل الدخول الموحد (SSO).
النهج 1: نسخ متعددة من discourse-auth-proxy
النهج 2: تعديل discourse-auth-proxy للتأثير على return_sso_url في الحمولة.
النهج 3: تنفيذ النهج 1 أو 2 بحيث يعني تسجيل الدخول مرة واحدة عدم الحاجة لتسجيل الدخول مرة أخرى عند الانتقال من site1.com إلى site2.com.

أقوم بوضعك في الإشارة @sam، لأنك كتبت برنامج Go discourse-auth-proxy الأصلي.

مرحباً.

أنا عالق في كيفية تعامل المزود مع الرمز + في عنوان URL المرتجع لـ SSO.

في حالتي، سينشئ مستهلك DiscourseConnect عنوان return_sso_url مثل:

  1. بصيغته الخام: http://example.com/foo/bar?wpLoginToken=123+\
  2. بعد ترميزه عبر PHP: http%3A%2F%2Fexample.com%2Ffoo%2Fbar%3FwpLoginToken%3D123%2B%5C

ثم سيعيد DiscourseConnect التوجيه إلى:

  1. http://example.com/foo/bar?wpLoginToken=123%20\&sso=foo&sig=bar
  2. http://example.com/foo/bar?wpLoginToken=123+\&sso=foo&sig=bar

المشكلة هي أن عنوان URL المرتجع سيتم معالجته بواسطة دالة urldecode في PHP (وهي سير العمل الأساسي في مصادقة MediaWiki)، مما سيؤدي إلى تغيير قيمة wpLoginToken بشكل غير متوقع من 123+\ إلى 123 \.

يبدو أنني وجدت السبب:

حسناً، يطبق العميل والخادم الترميز وفك الترميز لكنهما يتبعان مواصفات مختلفة.

لا أطلب من Discourse إجراء تغيير، بل أبحث عن نصيحة لحل هذه المشكلة.

شكراً.

تعديل:
لقد حللت المشكلة ببساطة عن طريق ترميز الرمز + مرتين عبر urlencode.

3 إعجابات

شكرًا لك!

أنا أحاول ذلك حاليًا. لقد أرسلت لك طلبين لدمج التغييرات (PRs) على GitHub، أحدهما لتحديث الوثائق والآخر لإصلاح خطأ واجهته.

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

في الإعدادات > تسجيل الدخول، إعدادا المزود الخاصين بـ DiscourseConnect غير متتاليين، ويبدوان متداخلين مع إعدادات DiscourseConnect:

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

4 إعجابات

@techAPJ هل يمكن استخدامه مع AWS Cognito؟ أريد إنشاء تطبيق في AWS Amplify لمجتمع Discourse الخاص بي وأريد أن يتم مصادقة تطبيقي عبر Discourse.

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

آسف على التأخير الطويل في الرد. أنت محق تمامًا — من المحير أن تكون متداخلة بهذه الطريقة. لقد قمت بتنظيفها في هذا طلب السحب:

6 إعجابات

@mdoggydog شكراً على التحديث الأخير لإضافة DiscourseSsoConsumer لـ MediaWiki. كنا نتساءل عما يجب فعله بشأن تسجيل خروج المستخدمين من الويكي الخاص بنا دون تسجيل الخروج من Discourse، وبالتأكيد لم نكن نريد $wgPluggableAuth_EnableAutoLogin، لأنه يمنع الوصول المجهول إلى الويكي. الإعداد $wgDiscourseSsoConsumer_AutoRelogin الذي أضفته هو بالضبط ما احتجناه.

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

مرحباً :wave:!

أحاول استخدام مثال PHP من المنشور الأصلي، لكن الطريقة التي يخزنون بها الأشياء لا معنى لها. إنهم يخزنون القيم فقط في قاعدة بيانات SQL بمفاتيح login و nonce. إذا أردت استخدام SQL لتخزين الـ nonces، كيف ستبدو قاعدة بيانات SQL الخاصة بي بالضبط؟

بعض المعلومات الأخرى التي قد تساعد هي ما أستخدم هذا من أجله - آمل ربط مستخدم Discourse بحساب Minecraft عن طريق إنشاء رابط SSO مرتبط بمعرف UUID الخاص بهم. عند تسجيل الدخول بنجاح باستخدام Discourse، سأقوم بتخزين معرف UUID الخاص بهم ومعرف Discourse في جدول.

حتى الآن، تمكنت من جعل مثال PHP يعمل، لكنني على ما أعتقد لا أفهم تمامًا كيف سأحتاج إلى تعديله ليعمل لحالتي. بشكل مثالي، أريد إنشاء الرابط من خلال طلب GET وإرساله إلى المستخدم، بحيث يرتبط معرف UUID بالفعل بالـ nonce.

شكراً لهذا المنشور، فلولاه لكنت أكثر ضياعاً!

تعديل: بالنسبة للـ nonces، هل من الأفضل تخزين الـ nonces في الجدول والبحث عن طريقها؟ أعرف أنني بحاجة إلى مطابقة الـ nonce، ولكن ما لم أتمكن من تمرير معلومات إضافية في عنوان URL لإعادة التوجيه (والذي لم أنجح في القيام به)، لست متأكدًا من كيفية الإشارة إلى الـ nonce بشكل صحيح.

إعجابَين (2)

لقد أنشأت دليلاً يسمح للمسؤول بتكوين DiscourseConnect عبر بروتوكول SAML القياسي عبر SimpleSAMLphp.

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

تفاصيل الرابط

/session/sso_provider?sso=bm9uY2U9NDA3YTVlNjg1ZTEwMDlh...

لست متأكدًا من سبب ظهور خطأ 502 bad gateway.

لقد قمت بتحرير جزء من قيمة المعلمة sso التي قدمتها. ما لم يعرف شخص ما مفتاحك السري، فلن يتمكن من فك تشفير القيمة، ولكن بدا من الأسلم عدم تقديم القيمة الكاملة. لن يكون ذلك مرتبطًا بالخطأ 502 الذي تواجهه.

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

يبدو أن هناك خطأ في قاعدة البيانات. لأنني جربت نفس المكون الإضافي والتكوين على موقع آخر لـ Discourse، وهو يعمل. كيف يمكنني إصلاح هذه المشكلة؟

يبدو أن محاولة المصادقة في discourse-auth-proxy باستخدام أسماء مستخدمين أو أسماء مجموعات غير ASCII (الصينية في حالتي) تؤدي إلى خطأ بسبب عدم قدرة ملفات تعريف الارتباط على احتواء هذه الأحرف. هذا هو إصلاحي: (إخلاء مسؤولية: أنا لست على دراية كبيرة بلغة golang)

diff --git a/main.go b/main.go
index 1b1dc28..18f8c9e 100644
--- a/main.go
+++ b/main.go
@@ -154,7 +154,12 @@ func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWr
        var username, groups string

        if err == nil && cookie != nil {
-               username, groups, err = parseCookie(cookie.Value, config.CookieSecret)
+               var value string
+               value, err = url.QueryUnescape(cookie.Value)
+               if err != nil {
+                       return
+               }
+               username, groups, err = parseCookie(value, config.CookieSecret)
        }

        if err == nil {
@@ -224,7 +229,7 @@ func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWr
                cookieData := strings.Join([]string{username, strings.Join(groups, "|")}, ",")
                http.SetCookie(w, &http.Cookie{
                        Name:     cookieName,
-                       Value:    signCookie(cookieData, config.CookieSecret),
+                       Value:    url.QueryEscape(signCookie(cookieData, config.CookieSecret)),
                        Expires:  expiration,
                        HttpOnly: true,
                        Path:     "/",
إعجاب واحد (1)

شكرا للإبلاغ! هل تمانع في تقديم طلب سحب (PR) مقابل مستودع GitHub حتى نتمكن من دمج هذا التغيير في الإصدار الرسمي؟

4 إعجابات