تسجيل الدخول الأحادي المخصص لا يعمل بعد إضافة secure_session كمعامل

مرحبًا! لقد قمنا بكتابة مكوّن إضافي مخصص لـ SSO لتجميع تفاصيل تسجيل الدخول الخاصة بشركتنا في حزمة يمكن لـ Discourse استخدامها للتعامل مع تسجيل الدخول وإنشاء الحسابات. مع الإصدار v2.7.0beta4، بدأنا في تلقي أخطاء تشير إلى أننا لم نوفر معلمة جديدة، وهي secure_session. لا أستطيع العثور على أي تفاصيل حول تنسيق هذه المعلمة أو ما يجب أن تحتويه. هل هناك أي توثيق إضافي متاح لهذا التحديث؟

شكرًا لك!

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

بالتأكيد! إليك مكدس الخطأ الذي نراه في نظام مراقبة الأداء (APM):

ArgumentError: missing keyword: :secure_session
…r/www/discourse/app/models/discourse_single_sign_on.rb:   28:in `initialize'
               /var/www/discourse/lib/single_sign_on.rb:   65:in `new'
               /var/www/discourse/lib/single_sign_on.rb:   65:in `parse'
…ourse_account_auth/lib/service_gateway_current_user.rb:   72:in `upsert_sso_record'
…ourse_account_auth/lib/service_gateway_current_user.rb:   53:in `create_sso_record'
…ourse_account_auth/lib/service_gateway_current_user.rb:   28:in `current_user'
                 /var/www/discourse/lib/current_user.rb:   36:in `current_user'

ملف service_gateway_current_user.rb هو جزء من الإضافة (plugin) الخاصة بنا لبناء الحمولة (payload) المرسلة إلى DiscourseSingleSignOn بناءً على رؤوس “بوابة الخدمة” (Service Gateway) — وهي البنية الداخلية لشركتنا لتحديد ما إذا كنت قد قمت بتسجيل الدخول إلى نظامنا.

لتوضيح تلك الجزء من المكدس:

  • دالة current_user الخاصة بنا تستخدم الرؤوس للبحث عن سجل SingleSignOnRecord حيث يتطابق external_id مع معرف المستخدم في الرؤوس. إذا لم يكن الأمر كذلك، ننتقل إلى قسم create_sso_record.
  • تقوم create_sso_record بإنشاء هاش — { external_id: sg_headers[:user_id], email: sg_headers[:email] } — وترسله إلى دالة upsert_sso_record الخاصة بنا.
  • تأخذ upsert_sso_record ذلك الهاش (المُشار إليه بـ payload في السياق أدناه) وتحاول إنشاء كائن DiscourseSingleSignOn:
def upsert_sso_record(payload)
  encoded_query = Base64.encode64(payload.to_query)
  sig = OpenSSL::HMAC.hexdigest('sha256', ENV['SSO_SECRET'], encoded_query)
  sso = DiscourseSingleSignOn.parse({ sso: encoded_query, sig: sig }.to_query)

  if SiteSetting.verbose_sso_logging
    Rails.logger.warn("Verbose SSO log: Started SSO process\n\n#{sso.diagnostics}")
    Rails.logger.warn("SSO Payload:\n\n#{payload}")
  end

  begin
    user = sso.lookup_or_create_user(@request.ip)
  rescue ActiveRecord::RecordInvalid => ex
    Rails.logger.error "Unable to find/create sso user #{ex}"
  end
  user
end

يبدو أن استدعاء parse في السطر الثالث من تلك الدالة هو المكان الذي تنشأ فيه المشكلة. بمجرد محاولة تهيئة الكائن، فإن قيمة secure_session المتوقعة غير موجودة.

تذكير! أنا أيضًا فضولي بشأن هذا!

أتساءل عما إذا كان تعيين إعداد الموقع الجديد discourse_connect_csrf_protection إلى false سيحل المشكلة لديك. هذا الإعداد مخفي، لذا يجب تعيينه من وحدة تحكم Rails. يمكنك العثور على التفاصيل المتعلقة به في الردود على هذا الموضوع: DiscourseConnect flow no longer functions.

للأسف، لا أعتقد أن الإعداد الجديد سيساعد بمفرده - فداخلات الكود ستظل تتطلب تمرير كائن secure_session، حتى لو لم يتم استخدامه.

بشكل عام، نوصي باستخدام الخطافات الرسمية لملفات التوثيق الإضافية، بدلاً من تجاوز تنفيذ DiscourseConnect الأساسي.

من الصعب التأكد من ذلك دون رؤية الإضافة بالكامل، لكن يمكنك تجربة تمرير قيمة nil لـ secure_session. قد يساعد ذلك، إلى جانب تفعيل إعداد الموقع الجديد، في تقريب الأمور قليلاً من العمل بشكل صحيح.

بعد الغوص أكثر في كود v2.7.0.beta4، أرى أن ApplicationController يحتوي على تعريف secure_session. يبدو أن تغيير كود الإضافة لدينا إلى ما يلي يعمل في بيئة الاختبار (Staging):

sso = DiscourseSingleSignOn.parse({ sso: encoded_query, sig: sig }.to_query, secure_session: secure_session)

…هل الأمر بهذه البساطة حقًا؟ :thinking:

يبدو أن هذا يجب أن يعمل - عادةً ما تأتي الجلسة الآمنة من تلك الطريقة في ApplicationController. :slight_smile:

رائع! شكراً لمساعدتي في مناقشة هذه المشكلة بصوت عالٍ. :duck: :metal: