مرحبًا ، لقد قمت بكتابة وحدة مصادقة SimpleSAMLphp هذه لتمكين استخدام Discourse كمزود SSO ضمن تثبيت SimpleSAMLphp. أي أنه يمكنك استخدام Discourse كمزود SSO لأي خدمات تدعم مصادقة SAML أو Shibboleth، وهو أمر رائع حقًا.
أخبرني برأيك (إذا كنت مهتمًا بالتعليق على الكود، يمكنك استخدام مشكلات GitHub).
هذا رائع! إذا كنت ترغب في جعل الوحدة أكثر وضوحًا، يمكنك إنشاء موضوع عنها في فئة #plugin:extras الخاصة بنا. هذه الفئة هي دليل لجميع الإضافات والتكاملات لـ Discourse التي ليست إضافات Discourse نفسها،
أنا أقوم بتطبيق نظام تسجيل الدخول الموحد (SSO) هذا على موقع ويب موجود، وأود فقط التحقق من كيفية “عرض” طريقة تسجيل الدخول للمستخدمين.
على سبيل المثال، لنفترض أن موقعي الإلكتروني على www.example.com يحتوي على زر “تسجيل الدخول” في شريط التنقل العلوي.
هل يجب أن ينقل هذا الزر الأشخاص فورًا إلى صفحة مصادقة تسجيل الدخول الخاصة بـ Discourse؟ أم أنه من الأفضل عرض صفحة أو نافذة منبثقة تحتوي على معلومات أولاً، شيء مثل:
أتساءل فقط عما إذا كان المستخدمون سيشعرون بالارتباك إذا لم يُخبروا بما هو قادم؟
هل لدى أي شخص أي تجارب مستخدم أو ممارسات مثالية للمشاركة؟
وشكرًا أيضًا لـ @techAPJ على المنشور الأول المفصل جدًا في هذا الموضوع، لقد تمكنت بنجاح من دمج هذا في موقعي الإلكتروني المبنى بـ ASP.NET من الصفر باتباع خطواتك
هل من الممكن تضمين معلمة حالة تُعاد دون تغيير، كما يُفعل في OAuth؟ يعتمد وسيط المصادقة في Asp.net core على إنشاء معرف ارتباط لمنع هجمات CSRF، ولا أملك حاليًا طريقة سهلة لتضمينه.
' إنشاء عنوان 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 المفككة:
هل توجد أمثلة أو توصيات لاستخدام Discourse كمزود لتسجيل الدخول الموحد (SSO) للمصادقة عبر مواقع متعددة؟
يبدو أن هناك طريقتين أساسيتين للعمل مع مواقع متعددة:
استخدام عدة نسخ من discourse-auth-proxy، نسخة واحدة لكل موقع محمي.
استخدام نسخة واحدة من 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 المرتجع سيتم معالجته بواسطة دالة urldecode في PHP (وهي سير العمل الأساسي في مصادقة MediaWiki)، مما سيؤدي إلى تغيير قيمة wpLoginToken بشكل غير متوقع من 123+\ إلى 123 \.
بما أن إعدادات المزود وغير المزود موجهة لحالات استخدام متعاكسة — أي استخدام Discourse لإدارة المستخدمين لشيء آخر مقابل استخدام شيء آخر لإدارة المستخدمين لـ Discourse — فإن عرض هذه الإعدادات بشكل مختلط يدعو إلى سوء التكوين. سيكون الأمر أقل إرباكًا إذا كان إعدادا المزود متتاليين، إما كليًا قبل أو كليًا بعد إعدادات غير المزود.
@mdoggydog شكراً على التحديث الأخير لإضافة DiscourseSsoConsumer لـ MediaWiki. كنا نتساءل عما يجب فعله بشأن تسجيل خروج المستخدمين من الويكي الخاص بنا دون تسجيل الخروج من Discourse، وبالتأكيد لم نكن نريد $wgPluggableAuth_EnableAutoLogin، لأنه يمنع الوصول المجهول إلى الويكي. الإعداد $wgDiscourseSsoConsumer_AutoRelogin الذي أضفته هو بالضبط ما احتجناه.
أحاول استخدام مثال PHP من المنشور الأصلي، لكن الطريقة التي يخزنون بها الأشياء لا معنى لها. إنهم يخزنون القيم فقط في قاعدة بيانات SQL بمفاتيح login و nonce. إذا أردت استخدام SQL لتخزين الـ nonces، كيف ستبدو قاعدة بيانات SQL الخاصة بي بالضبط؟
بعض المعلومات الأخرى التي قد تساعد هي ما أستخدم هذا من أجله - آمل ربط مستخدم Discourse بحساب Minecraft عن طريق إنشاء رابط SSO مرتبط بمعرف UUID الخاص بهم. عند تسجيل الدخول بنجاح باستخدام Discourse، سأقوم بتخزين معرف UUID الخاص بهم ومعرف Discourse في جدول.
حتى الآن، تمكنت من جعل مثال PHP يعمل، لكنني على ما أعتقد لا أفهم تمامًا كيف سأحتاج إلى تعديله ليعمل لحالتي. بشكل مثالي، أريد إنشاء الرابط من خلال طلب GET وإرساله إلى المستخدم، بحيث يرتبط معرف UUID بالفعل بالـ nonce.
شكراً لهذا المنشور، فلولاه لكنت أكثر ضياعاً!
تعديل: بالنسبة للـ nonces، هل من الأفضل تخزين الـ nonces في الجدول والبحث عن طريقها؟ أعرف أنني بحاجة إلى مطابقة الـ nonce، ولكن ما لم أتمكن من تمرير معلومات إضافية في عنوان URL لإعادة التوجيه (والذي لم أنجح في القيام به)، لست متأكدًا من كيفية الإشارة إلى الـ nonce بشكل صحيح.
لقد قمت بتحرير جزء من قيمة المعلمة sso التي قدمتها. ما لم يعرف شخص ما مفتاحك السري، فلن يتمكن من فك تشفير القيمة، ولكن بدا من الأسلم عدم تقديم القيمة الكاملة. لن يكون ذلك مرتبطًا بالخطأ 502 الذي تواجهه.
يبدو أن محاولة المصادقة في 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: "/",