لدي إضافة JS على موقع Discourse الخاص بي. تستخدم هذه الإضافة JS خدمة PocketBase لتخزين البيانات. PocketBase هي خدمة SQLite “بدون خادم” تسمح لي بتخزين الملفات و JSON blobs. تمتلك PocketBase نظام مصادقة رائع قائم على JWT، بحيث بمجرد حصول المستخدم على رمز مصادقة، يمكنه تخزين البيانات بشكل آمن مباشرة في PocketBase (دون المرور عبر خادم خلفي، وما إلى ذلك) مباشرة من JS على جانب العميل.
أحاول إيجاد طريقة يمكنني من خلالها إنشاء تسجيل دخول على جانب PocketBase تلقائيًا عندما يقوم مستخدم بتسجيل الدخول إلى Discourse.
كانت محاولتي الأولى هي جعل إضافة JS تقوم باستدعاء إلى مسار على الخادم وتضمين ملفات تعريف الارتباط الخاصة بمصادقة Discourse. ثم، لهذا المسار، اسمح لـ nginx بتوجيهه إلى خدمة (“login proxy”) يمكنها فك تشفير ملفات تعريف الارتباط الخاصة بالمصادقة وتحديد هوية المستخدم. مع معلومات المستخدم الموثقة، يمكن لـ login proxy بعد ذلك إجراء استدعاء خاص إلى PocketBase والحصول على رمز مصادقة PocketBase، ثم إعادة إرسال رمز مصادقة PocketBase هذا الذي يمكن لـ JS على جانب العميل استخدامه لإجراء طلبات لاحقة مباشرة إلى PocketBase.
لكنني أواجه صعوبة في فك تشفير ملفات تعريف الارتباط الخاصة بمصادقة Discourse (أتخيل أن _t هو ملف تعريف الارتباط الصحيح، لكنني لا أرى طريقة بسيطة للوصول إلى تفاصيل المستخدم وأخشى أن يتغير الهيكل على أي حال).
هل هناك طريقة أذكى للوصول بأمان إلى عنوان البريد الإلكتروني لمستخدم مسجل الدخول؟ لا أعتقد أن هذا يجب أن يحدث على جانب العميل، وأفضل القيام بذلك على جانب الخادم لأسباب أمنية واضحة.
لا أعرف ما يكفي عن المكدس الخاص بك أو حالة الاستخدام، ولكن أعتقد أنني قمت بحل مشكلة مماثلة من قبل، وقد تكون بعض الأفكار مفيدة لك.
لدي تطبيق Next.js حيث أحتاج إلى جانب العميل للحصول على JWT صالح لإجراء مكالمات إلى واجهة برمجة تطبيقات الواجهة الخلفية الخاصة بي إذا كانت هناك جلسة Discourse.
في حالتي، أقوم بذلك باستخدام استدعاء fetch واحد من جانب العميل مع { credentials: "include" }، والذي يعمل فقط لأن لدي كل شيء معدًا بنطاق واحد ويتبع استدعاء fetch عمليات إعادة التوجيه بشفافية.
يقوم العميل الخاص بي بجلب /auth/token مخصص، والذي يتحقق من وجود _t (فقط لتجنب إعادة توجيه غير مجدية بخلاف ذلك) ويعيد توجيهًا إلى عنوان URL آمن /session/sso_provider تم بناؤه باتباع المستندات في الموضوع المرتبط، مع nonce/sso/sig، و return_sso_url يشير إلى /auth/callback مخصص، والذي سيستخرج البيانات التي أرسلها Discourse، ويبني ويعيد رمز JWT الذي يمكن لعميلي استخدامه من هذه اللحظة فصاعدًا.
أعتقد أنه يمكن حل حالة الاستخدام الخاصة بك بطريقة مماثلة.
هل هذا يعني أنني بحاجة إلى تفويض إدارة المستخدمين بالكامل إلى تطبيق connect؟ لست متأكدًا مما إذا كنت أرغب في القيام بذلك، إذا كان الأمر كذلك.
إذا كان connect مجرد طبقة إضافية فوق إدارة مستخدمي discourse الحالية، فهذا يبدو قابلاً للتطبيق.
ولكن، عندما بدأت في القراءة عن discourse connect، أخشى أنني بحاجة الآن إلى بناء وصيانة تطبيق جديد تمامًا لإدارة مصادقة المستخدم، ولا أعرف حقًا كيف أحدد نطاق هذا الآن.
يفترض ردي أنك تستخدم Discourse كموفر الهوية الخاص بك (مع واجهات تسجيل الدخول/الاشتراك الخاصة به)، وترغب في الحفاظ على ذلك.
على جانب Discourse، يعد تمكينه بسيطًا مثل
ومع ذلك، ذكرت أنك تقوم بإنشاء إضافة.
إذا قمت بإنشاء “مسار على الخادم” في إجراء وحدة تحكم جديد في إضافة Discourse، يمكنك الحصول على المستخدم من الجلسة، واستدعاء أطراف ثالثة وإرجاع JWT إلى عميلك.
ولكن أعتقد أن هذا إذا كنت أرغب في إرسال مستخدمي إلى موقع ثانوي وإدارة المصادقة هناك.
في حالتي، لدي جزء من جافاسكريبت يعمل على موقع discourse. وأريد أن يقوم هذا الجافاسكريبت بالاتصال بمسار على نفس الخادم والحصول على ملف تعريف ارتباط (cookie) لـ pocketbase.
أنا في الواقع أستخدم وكيل nginx أمام discourse، ولذلك أضفت للتو مسارًا خاصًا /pb/auth (على سبيل المثال). عندما يصل جافاسكريبت الخاص بي إلى هذا المسار، فإن خادم وكيل خلفي (ليس داخل discourse) يقبل هذا الاتصال، ويحاول فك تشفير ملف تعريف الارتباط للجلسة _t.
كنت أفعل ذلك بهذه الطريقة لأنها تبدو أسهل قليلاً من إضافة مكون إضافي لـ discourse (لدي معرفة أقل بذلك وإعداد التطوير، إلخ). إذا كان الأمر مجرد مسألة فك تشفير ملف تعريف ارتباط باستخدام base64 وتجزئة sha، فقد اعتقدت أن ذلك سيعطيني حمولة آمنة لإخباري بمن هو المستخدم.
ولكن، إذا كنت تعتقد أن هناك طريقة مباشرة لبناء مكون إضافي يضيف هذا المسار إلى discourse، فأنا مهتم جدًا بتجربتها. يبدو أنها الطريقة الصحيحة على المدى الطويل. ولكن، أنا مبرمج Perl قديم، لذا أفضل الطريق الأسهل، وكان مسار nginx الخاص بي يبدو أسهل.
على العكس تمامًا: إذا كان لديك “موقع” منفصل (PocketBase في هذا المثال) وتريد أن يكون Discourse هو المصدر الموثوق لإدارة المستخدمين/المصادقة - مثل مثال Next.js الخاص بي.
للوهلة الأولى، أحتاج إلى أن أسأل: هل يضيف هذا البرنامج التعليمي رمزًا إلى تثبيت Rails الأساسي لـ Discourse؟ أنا على ما يرام مع القيام بذلك إذا كانت هذه هي الطريقة الرسمية، ولكن يبدو أن هذا خطير وسيكون من الأفضل التعامل معه كمكون إضافي (يمكن إلغاء تثبيته أو تعطيله بسهولة). أيضًا، ألا يجب أن أقلق من أن هذا سيكسر ترقيات Discourse إذا لم يكن الكود الخاص بي في مستودع GitHub؟
على سبيل المثال هنا:
هل هذا يعني أنني سأدخل إلى الحاوية (./launcher enter app) ثم أقوم بتحرير /var/www/app/controllers/snack_controller.rb؟
في الواقع، لقد اتبعت هذه التعليمات للتو. لا يمكنني جعل المسار /admin/snack.json يعمل، حتى بعد تشغيل ./launcher rebuild app.
يبدو أن هذا البرنامج التعليمي قديم بحوالي ثماني سنوات. هل هذه حقًا هي الطريقة الصحيحة للقيام بالأشياء؟
حسنًا، لقد حاولت اتباع التعليمات. حاولت استخدام الأمر rake plugin:create[pocketbase-auth]داخل الحاوية (حيث لن يكون rake متاحًا في الخارج، أليس كذلك). لكنه يفشل فشلاً ذريعًا لأنني لا أملك git معدًا داخل الحاوية.
كما قرأت لاحقًا، يبدو أنني بحاجة إلى تحديد مستودع git الخاص بالمكون الإضافي لعرض مكون إضافي في قسم المسؤول. لكنني لم أصل إلى النقطة التي لدي فيها حتى نسخة تعمل بشكل مقبول من المكون الإضافي وليس لدي أشياء داخل مستودع git.
تحرير: لم أقرأ بعناية، وبالفعل يتطلب هذا إعداد تطوير، وهو ما تم توضيحه في البداية. سأعمل على ذلك وسأعود إلى هذا.
أشك في أن هذه الصعوبات تحدث لأن المكونات الإضافية عادة ما يتم تطويرها مقابل إعداد “تطوير” لـ discourse، وليس داخل حاوية docker التي أقوم بتشغيلها. هذا جيد، لكن أتمنى لو بدأت أدلة مطوري المكونات الإضافية بهذا الافتراض والتعليمات حول كيفية التشغيل بهذه الطريقة. الطريقة الموصى بها لتشغيل discourse هي استخدام docker (والتي أحبها) ولكن أعتقد أن هناك فجوة بين كيفية تشغيل الأشياء داخل docker والقيام بالتطوير داخل المستندات.
# rake plugin:create[pocketbase-auth]
Cloning 'https://github.com/discourse/discourse-plugin-skeleton' to '/var/www/discourse/plugins/pocketbase-auth'...
Initializing git repository...
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /var/www/discourse/plugins/pocketbase-auth/.git/
Author identity unknown
*** Please tell me who you are.
Run
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
to set your account's default identity.
Omit --global to set the identity only in this repository.
fatal: unable to auto-detect email address (got 'discourse@community-public-do-vm-app.(none)')
rake aborted!
Command failed with exit 128: git
/var/www/discourse/lib/tasks/plugin.rake:356:in `system'
/var/www/discourse/lib/tasks/plugin.rake:356:in `block (2 levels) in <main>'
/var/www/discourse/lib/tasks/plugin.rake:346:in `chdir'
/var/www/discourse/lib/tasks/plugin.rake:346:in `block in <main>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'
Tasks: TOP => plugin:create
(See full trace by running task with --trace)