إنشاء رابط تسجيل دخول DiscourseConnect

:bookmark: تشرح هذه الوثائق كيفية إنشاء روابط على موقع مزود DiscourseConnect تقوم بتسجيل دخول المستخدمين إلى Discourse وإعادة توجيههم إلى عنوان URL محدد في Discourse.

:person_raising_hand: مستوى المستخدم المطلوب: المسؤول

يمكن للمواقع التي تستخدم DiscourseConnect إضافة روابط على موقع مزود DiscourseConnect الخاص بها تقوم بتسجيل دخول المستخدمين إلى Discourse وإعادة توجيههم إلى عنوان URL محدد في Discourse. يتم ذلك عن طريق إنشاء روابط تشير إلى المسار /session/sso مع تعيين معلمة return_path إلى مسار صفحة Discourse التي تريد أن ينتهي بها المستخدمون.

يجب أن يكون خاصية href للرابط بالشكل أدناه، مع استبدال المسار الذي تريد أن ينتهي به المستخدمون بـ \u003crelative_path\u003e:

https://forum.example.com/session/sso?return_path=\u003crelative_path\u003e

مثال على وسم ربط يقوم بتسجيل دخول مستخدم وإعادة توجيهه إلى الصفحة الرئيسية لموقع Discourse:

\u003ca href=\"https://forum.example.com/session/sso?return_path=/\"\u003eالمجتمع\u003c/a\u003e

مثال على وسم ربط يقوم بتسجيل دخول مستخدم وإعادة توجيهه إلى صفحة أهم المواضيع:

\u003ca href=\"https://forum.example.com/session/sso?return_path=/top\"\u003eأهم المواضيع\u003c/a\u003e

كيفية تخزين مسار العودة (return_path) في Discourse

يخزن Discourse قيمة المعلمة return_path في جلسة الخادم، مفهرسة بواسطة رمز عدم التكرار (nonce) الخاص بـ SSO الذي يتم إنشاؤه عندما يزور المستخدم المسار /session/sso. في نهاية عملية المصادقة الخاصة بـ DiscourseConnect، يبحث Discourse عن return_path باستخدام رمز عدم التكرار ويعيد توجيه المستخدمين إلى هذا المسار.

جعل العملية سلسة للمستخدمين المصادق عليهم

عندما يزور المستخدم مسار /session/sso الخاص بـ Discourse، يتم إعادة توجيهه إلى عنوان URL المحدد بواسطة إعداد الموقع discourse connect url. سيقوم مزود DiscourseConnect بعد ذلك بالتعامل مع عملية المصادقة بنفس الطريقة التي يتعامل بها إذا نقر المستخدم على زر \u003cbutton\u003eتسجيل الدخول\u003c/button\u003e الخاص بـ Discourse.

لكي تكون عملية المصادقة سلسة للمستخدمين الذين قاموا بتسجيل الدخول بالفعل على موقع مزود المصادقة، يحتاج كود DiscourseConnect الخاص بمزود المصادقة إلى التحقق مما إذا كان المستخدم قد قام بتسجيل الدخول أم لا. إذا لم يكن المستخدم قد سجل دخوله، يتم أخذه خلال عملية تسجيل الدخول الخاصة بمزود المصادقة. إذا كان المستخدم قد سجل دخوله بالفعل، يتم تخطي عملية تسجيل الدخول على موقع مزود المصادقة.

إليك مثال مشروح، باستخدام كود من إضافة WP Discourse. ويوضح كيف يمكن التعامل مع المستخدمين المصادق عليهم بشكل مختلف عن المستخدمين غير المصادق عليهم:

public function sso_parse_request( $wp ) {
    // تحقق مما إذا كان تسجيل الدخول الموحد (SSO) ممكّنًا في خيارات الإضافة
    if ( empty( $this-\u003eoptions['enable-sso'] ) ) {
        return null;
    }

    // التعامل مع أي طلبات تسجيل خروج قبل المتابعة مع تسجيل الدخول الموحد
    $this-\u003ehandle_logout_request();

    // تحقق مما إذا كان المعلمتان 'sso' و 'sig' موجودتين في متغيرات الاستعلام
    if ( array_key_exists( 'sso', $wp-\u003equery_vars ) \u0026\u0026 array_key_exists( 'sig', $wp-\u003equery_vars ) ) {
        // تطهير حمولة 'sso' والتوقيع لضمان أنها آمنة للاستخدام
        $payload = sanitize_text_field( $wp-\u003equery_vars['sso'] );
        $sig     = sanitize_text_field( $wp-\u003equery_vars['sig'] );

        // إذا لم يكن المستخدم قد سجل الدخول إلى ووردبريس، قم بإعادة توجيهه إلى صفحة تسجيل الدخول
        // هذا يضمن مطالبة المستخدمين الذين ليس لديهم جلسة نشطة بتسجيل الدخول إلى ووردبريس أولاً
        if ( ! is_user_logged_in() ) {
            // بناء عنوان URL لإعادة التوجيه إليه بعد تسجيل الدخول
            $redirect = add_query_arg( $payload, $sig );
            // إنشاء عنوان URL لتسجيل الدخول في ووردبريس مع معلمة إعادة التوجيه
            $login    = wp_login_url( esc_url_raw( $redirect ) );

            // تشغيل إجراء قبل إعادة التوجيه لتسجيل الدخول (اختياري للتسجيل أو الإجراءات المخصصة)
            do_action( 'wpdc_sso_before_login_redirect', $redirect, $login );

            // إعادة التوجيه إلى صفحة تسجيل الدخول في ووردبريس
            return $this-\u003eredirect_to( $login );
        } else {
            // إذا كان المستخدم مصادقًا عليه بالفعل في ووردبريس، تخطي عملية تسجيل الدخول
            // والمتابعة مع التحقق من صحة حمولة وتوقيع تسجيل الدخول الموحد.
            $sso_secret = $this-\u003eoptions['sso-secret'];
            $sso        = new SSO( $sso_secret );
            
            // التحقق من صحة الحمولة والتوقيع باستخدام سر تسجيل الدخول الموحد
            if ( ! ( $sso-\u003evalidate( $payload, $sig ) ) ) {
                // التعامل مع طلبات تسجيل الدخول الموحد غير الصالحة
                return $this-\u003ehandle_error( 'parse_request.invalid_sso' );
            }

            // الحصول على مستخدم ووردبريس المسجل دخوله حاليًا
            $current_user = wp_get_current_user();
            // إعداد معلمات تسجيل الدخول الموحد باستخدام بيانات المستخدم المسجل دخوله
            $params       = $this-\u003eget_sso_params( $current_user );

            try {
                // إنشاء رمز عدم تكرار من الحمولة وبناء سلسلة تسجيل الدخول الموحد
                $params['nonce'] = $sso-\u003eget_nonce( $payload );
                $q               = $sso-\u003ebuild_login_string( $params );
            } catch ( \\Exception $e ) {
                // التعامل مع الاستثناءات إذا كانت هناك مشكلة في إنشاء معلمات تسجيل الدخول الموحد
                return $this-\u003ehandle_error( 'parse_request.invalid_sso_params', array( 'message' =\u003e esc_html( $e-\u003egetMessage() ) ) );
            }

            // تشغيل إجراء قبل إعادة توجيه المستخدم لتسجيل الدخول الموحد (مفيد للتسجيل)
            do_action( 'wpdc_sso_provider_before_sso_redirect', $current_user-\u003eID, $current_user );

            // تسجيل نجاح تسجيل الدخول الموحد إذا كان التسجيل المطول ممكّنًا
            if ( ! empty( $this-\u003eoptions['verbose-sso-logs'] ) ) {
                $this-\u003elogger-\u003einfo( 'parse_request.success', array( 'user_id' =\u003e $current_user-\u003eID ) );
            }

            // إعادة توجيه المستخدم المصادق عليه إلى عنوان URL لتسجيل الدخول لـ DiscourseConnect مع سلسلة تسجيل الدخول الموحد
            return $this-\u003eredirect_to( $this-\u003eoptions['url'] . '/session/sso_login?' . $q );
        }
    }

    // إرجاع null إذا لم يتم العثور على معلمات تسجيل دخول موحد في الطلب
    return null;
}

تعيين مسار العودة إلى عناوين URL غير تابعة لـ Discourse

يسمح Discourse بتسجيل دخول مستخدم وإعادة توجيهه إلى عنوان URL غير تابع لـ Discourse. لاحظ أنه لكي يعمل هذا، تحتاج إلى إضافة النطاق إلى إعداد الموقع discourse connect allowed redirect domains. افتراضيًا، يكون هذا الإعداد فارغًا - مما يمنع إعادة التوجيه إلى عناوين URL غير تابعة لـ Discourse. يمكنك أيضًا استخدام * كحرف بدل للسماح لجميع النطاقات. إذا قمت بتمكينه، تأكد من استخدام عنوان URL المطلق في معلمة return_path لأي عناوين URL غير تابعة لـ Discourse تريد توجيه المستخدمين إليها.

21 إعجابًا

أنا أستخدم هذه الطريقة ولكن في كل مرة أحتاج إلى تسجيل الدخول عبر sso.
كيف يمكننا جعل الأمر سلسًا، مما يعني أنه إذا قمت بتسجيل الدخول بالفعل إلى discourse، فلن تكون هناك حاجة للذهاب إلى صفحة sso لتسجيل الدخول مرة أخرى؟

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

ما لم يتغير شيء ما، فهذه هي الطريقة المتوقعة للعمل. على سبيل المثال، إذا كنت مسجلاً الدخول إلى Discourse وانقر على رابط في موقع موفر SSO يشير إلى https://forum.example.com/session/sso?return_path=/t/some-slug/23، فيجب إعادة توجيهك بسلاسة إلى /t/some-slug/23 دون الحاجة إلى زيارة صفحة تسجيل الدخول أولاً.

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

أنا بالفعل على آخر تحديث لـ discourse وهذه هي طريقة عمل تسجيل الدخول الأحادي (SSO) بالنسبة لي:

كما ترى، لقد تم تسجيل دخولي بالفعل، ولكن عندما أدخل عنوان URL مثل https://forum.example.com/session/sso?return_path=/t/some-slug/23، سأتم إعادة توجيهي إلى صفحة تسجيل الدخول الأحادي (SSO) مرة أخرى.

أعتقد أن ما يحدث هو أنه عند زيارة مسار مثل https://forum.example.com/session/sso?return_path=/t/some-slug/23، يقوم Discourse بإعادة توجيهك إلى discourse connect url، بغض النظر عما إذا كنت مسجلاً الدخول إلى Discourse أم لا. يحدث هذا هنا:

من المتوقع بعد ذلك أن يتعامل موقع موفر SSO مع حالة المستخدمين الذين قاموا بتسجيل الدخول بالفعل إلى الموقع. إليك كيف يتعامل المكون الإضافي WP Discourse مع الأمر:

هذا الرمز (ما يلي عبارة else) يتعامل مع حالة المستخدمين الذين قاموا بتسجيل الدخول بالفعل إلى WordPress. يتم إعادة توجيههم مرة أخرى إلى عنوان URL الذي يتم توفيره بواسطة معلمة الاستعلام return_path. لذلك من وجهة نظر المستخدم، يتم نقلهم مباشرة إلى عنوان URL للمسار المرتجع، ولكن ما يحدث بالفعل هو أنهم يعاد توجيههم إلى موقع موفر SSO، ثم مرة أخرى إلى Discourse.

أعتقد أن المشكلة في موقعك هي أن رمز SSO الخاص بك لا يتعامل مع حالة المستخدمين الذين قاموا بتسجيل الدخول بالفعل إلى الموقع.

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

3 إعجابات

شكرا جزيلا على شرحك.

نعم، هذا شيء سنقوم بإصلاحه في الدخول الأحادي الخاص بنا.

ولكن

أعتقد أن وجود هذا الفحص من جانب Discourse كان سيخلق تجربة مستخدم أفضل.

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

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

ربما يمكن دمج نسخة أقل تفصيلاً من هذا الموضوع في Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso) - #482. لم يتم ذكر المعلمة return_path في هذا الموضوع.