مشكلة SSO: المعلمات SSO أو SIG مفقودة

مرحباً، لدي مشكلة في Discourse SSO. ماذا أفعل بشكل خاطئ؟ الكود الخاص بي أدناه يستخرج من منصتي الأخرى دون أي مشكلة. ومع ذلك، لا أحصل على أي nonce.


// تمكين تسجيل الأخطاء لتصحيح الأخطاء
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// تحميل ملف التهيئة
require_once '/init.php'; // قم بتحديث هذا المسار بناءً على إعداد منصتك

// مفتاح Discourse Connect السري وعنوان URL لإرجاع الحمولة
$sso_secret = 'keyhere'; // استبدل بمفتاحك السري المشترك في Discourse
$discourse_url = 'https://urlhere.com/session/sso_login'; // استبدل بعنوان URL الخاص بـ Discourse

// بدء الجلسة للتحقق من حالة تسجيل دخول مستخدم المنصة
session_start();

// التحقق مما إذا كان المستخدم مسجلاً للدخول
if (!isset($_SESSION['uid'])) {
    // إذا لم يكن المستخدم مسجلاً للدخول، قم بإعادة التوجيه إلى صفحة تسجيل الدخول للمنصة
    header('Location: /clientarea.php');
    exit;
}

// تصحيح الأخطاء: تسجيل معلمات الطلب الواردة
error_log("Received GET parameters: " . print_r($_GET, true));

// التحقق مما إذا كنا قد تلقينا معلمات 'sso' و 'sig' من Discourse
if (!isset($_GET['sso']) || !isset($_GET['sig'])) {
    error_log("Missing SSO or SIG parameters.");
    header('Location: /clientarea.php');
    exit;
}

// التحقق من صحة توقيع SSO باستخدام المفتاح السري
$sso = $_GET['sso'];
$sig = $_GET['sig'];
$expected_sig = hash_hmac('sha256', $sso, $sso_secret);

if ($sig !== $expected_sig) {
    error_log("Invalid SSO signature. Expected: $expected_sig, Received: $sig");
    header('Location: /clientarea.php');
    exit;
}

// جلب تفاصيل عميل المنصة
$clientDetails = localAPI('getclientsdetails', ['clientid' => $_SESSION['uid']], 'admin');
if ($clientDetails['result'] !== 'success' || !isset($clientDetails['userid'])) {
    error_log("Failed to fetch Platform client details.");
    header('Location: /clientarea.php');
    exit;
}

// استخراج تفاصيل المستخدم
$userId = $clientDetails['userid'];
$email = $clientDetails['email'];
$firstName = $clientDetails['firstname'];
$lastName = $clientDetails['lastname'];
$username = $firstName . ' ' . $lastName;

// فك ترميز حمولة SSO
$sso_payload = base64_decode($sso);
parse_str($sso_payload, $sso_params);

if (!isset($sso_params['nonce'])) {
    error_log("Nonce is missing from SSO payload.");
    header('Location: /clientarea.php');
    exit;
}

// إعداد حمولة SSO للإرجاع مع تفاصيل المستخدم
$return_payload = [
    'nonce' => $sso_params['nonce'],
    'email' => $email,
    'external_id' => $userId,
    'username' => $username,
    'name' => $firstName . ' ' . $lastName,
    'admin' => 0, // اضبط على 1 إذا كان المستخدم مسؤولاً، وإلا اتركه 0
    'moderator' => 0 // اضبط على 1 إذا كان المستخدم مشرفاً، وإلا اتركه 0
];

// ترميز الحمولة للإرجاع باستخدام base64
$query_string = http_build_query($return_payload);
$encoded_payload = base64_encode($query_string);

// توقيع الحمولة المشفرة باستخدام مفتاح Discourse السري
$return_sig = hash_hmac('sha256', $encoded_payload, $sso_secret);

// تصحيح الأخطاء: تسجيل الحمولة والتوقيع
error_log("Return Payload: " . print_r($return_payload, true));
error_log("Encoded Payload: $encoded_payload");
error_log("Return Signature: $return_sig");

// إعادة التوجيه إلى Discourse مع الحمولة الموقعة
header("Location: $discourse_url?sso=" . urlencode($encoded_payload) . "&sig=" . urlencode($return_sig));
exit;

سجلات الأخطاء:

[25-Sep-2024 14:50:17 UTC] Missing SSO or SIG parameters.
[25-Sep-2024 14:53:59 UTC] Received GET parameters: Array
(
[sso] => nonce_from_discourse
)

[25-Sep-2024 14:53:59 UTC] Missing SSO or SIG parameters.

لست متأكداً لماذا؟

أنا لست متأكدًا أيضًا. هل تم تكوين DiscourseConnect على موقع Discourse الخاص بك؟ كيف يصل المستخدمون إلى عنوان URL الذي يتعامل معه هذا الرمز؟

قد يوفر المرور عبر عملية المصادقة مع فتح أداة فحص المتصفح الخاص بك على علامة تبويب الشبكة الخاصة به بعض التفاصيل حول ما يحدث.

شكرًا على الرد.

أحاول التكامل مع WHMCS. لقد قمت بإعداد كل شيء في الكود بشكل مناسب وتم تمكين الإعدادات داخل Discourse.

يمكنني الحصول على جزء من الاستجابة ولكن ينقصني التوقيع (sig). كنت أعتقد أنه قد يكون خطأ في فك التشفير حيث يبدو أن هناك تباينًا بين النظامين.

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

حاولت قدر الإمكان تصحيح الأخطاء، وأعدت بناء Discourse. تسجيل خطوة بخطوة. جربت ChatGPT. قارنتها مع كود إضافة WordPress. لقد توقفت.

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

على Discourse، تأكد من تكوين الإعدادات التالية:

يجب تعيين إعداد discourse connect url إلى عنوان URL الذي يتعامل مع الرمز الذي نشرته.

قم بتعيين إعداد discourse connect secret إلى سلسلة نصية لا تقل عن 10 أحرف. لاحظ أن لديك السلسلة المكونة من 7 أحرف keyhere مُضمنة في الرمز الذي نشرته. أفترض أنك تقوم بتغيير هذه القيمة عند تشغيل الرمز. قم بتعيينها إلى نفس القيمة التي أدخلتها على Discourse.

الآن قم بتسجيل الخروج من موقع Discourse الخاص بك. افتح علامة تبويب الشبكة في فاحص الويب الخاص بمتصفحك. انقر فوق الزر “تسجيل الدخول” على Discourse. يجب أن ترى طلبات مشابهة لأول طلبين في لقطة الشاشة أدناه:

سيكون الطلب الأول إلى http://forum.example.com/session/sso?return_path=%2F

يجب أن يكون الطلب التالي إلى https://example.com/?sso=<sso_payload_sent_from_discourse>&sig=<sso_signature>

يجب تعيين example.com و forum.example.com إلى النطاقات الفعلية التي تستخدمها.

إذا تم تكوين كل شيء بشكل صحيح، أتوقع أن يقوم هذا بتعيين قيم المعاملين sso و sig إلى المتغيرات التي قمت بتعيينها هنا:

$sso = $_GET['sso'];
$sig = $_GET['sig'];

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

مع تمكين DiscourseConnect، يمكنك تسجيل الدخول مرة أخرى إلى موقع Discourse الخاص بك عن طريق زيارة المسار /u/admin-login. إذا كان لديك وصول إلى وحدة تحكم Rails الخاصة بموقع Discourse، يمكنك أيضًا تسجيل الدخول عن طريق تعطيل DiscourseConnect من وحدة تحكم Rails:

SiteSetting.enable_discourse_connect = false

من الممكن وجود أخطاء أخرى في الرمز الذي نشرته. على سبيل المثال، أعتقد أنك بحاجة إلى استدعاء urldecode على قيمة المعامل sso قبل إنشاء التوقيع المتوقع. ألق نظرة على كيفية تعامل إضافة WP Discourse مع الأمر:

$payload في الدالة أعلاه هو ببساطة قيمة معلم الاستعلام sso، بعد تنقيته هنا: wp-discourse/lib/sso-provider/discourse-sso.php at main · discourse/wp-discourse · GitHub.

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