هل يمكنني استخدام واجهة برمجة تطبيقات Discourse لمصادقة المستخدمين في تطبيق آخر؟

لدي منتدى Discourse يعمل، حيث يمكن للمستخدمين إنشاء تسجيل دخول محلي (اسم مستخدم + كلمة مرور).

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

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

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

ما هي نقطة نهاية واجهة برمجة التطبيقات للتحقق من اسم المستخدم وكلمة المرور لتسجيل الدخول إلى المنتدى؟

3 إعجابات

بشكل مباشر أكثر، يمكنك استخدام DiscourseConnect كآلية للتحقق من المستخدمين أو في مقدمة تطبيقك، استخدم discourse-auth-proxy.

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

5 إعجابات

في الواقع، “تطبيقي الآخر” هو تطبيق سطح مكتب، وليس تطبيق ويب. لا أعتقد أن discourse-auth-proxy سيعمل في هذه الحالة.

في صفحة DiscourseConnect، أحد العبارات الأولى هي:

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

هذا هو عكس ما أريد فعله تمامًا: أريد الاستعانة بجميع عمليات تسجيل الدخول إلى Discourse. هل هناك طريقة لاستخدام DiscourseConnect للقيام بذلك؟

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

نعم، بالتأكيد.

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

قد يعمل وضع وكيل المصادقة (auth-proxy) أمام خدمة ويب مصغرة مخصصة تمنح رمزًا موقعًا لتطبيقك بشكل جيد.

أنا متأكد من وجود طرق أخرى للقيام بذلك لا أفكر فيها.

[اقتباس=“Michael Brown, post:4, topic:266322, username:supermathie”]
الشيء الصعب هو أن هناك سرًا مشتركًا بين المزود (Discourse) والمستهلك (تطبيقك)
[/اقتباس]

هل تشير إلى مفتاح واجهة برمجة التطبيقات (API key)؟ يبدو من الممكن إنشاء مفتاح واجهة برمجة تطبيقات “دقيق”، لديه حق الوصول إلى نقاط نهاية واجهة برمجة تطبيقات محددة فقط. لا يزال غير واضح بالنسبة لي نقاط النهاية المطلوبة، إذا استخدمت هذا النهج. هل تعرف؟

نعم، قد تكون خدمة ويب بسيطة مع وكيل مصادقة (auth-proxy) حلاً جيدًا؛ سأضطر إلى التجربة قليلًا لمعرفة ذلك.

ليس بالضبط - ستكون قيمة أسرار موفر الاتصال في ديسكورس للتطبيق والتي ستحتاج إلى تعيينها بالاقتران مع تمكين موفر الاتصال في ديسكورس.

مزيد من المعلومات حول هذا موضح هنا: Use Discourse as an identity provider (SSO, DiscourseConnect)

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

ربما تكون هذه الطريقة المستخدمة في مثال React Native هذا مفيدة لك كتطبيق لسطح المكتب:

https://github.com/pmusaraj/discourse-mobile-single-site-app/blob/main/js/Authenticate.js

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

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

أتفهم أن النهج الذي أفكر فيه لن يدعم المصادقة الثنائية (TFA) ما لم أقم بتنفيذها بنفسي، وأنه لن يدعم تسجيل الدخول عبر موفري الطرف الثالث (Google، Facebook، Discord، …)

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


curl 'https://try.discourse.org/session' \
  -H 'sec-ch-ua: "Chromium";v="113", "Not-A.Brand";v="24"' \
  -H 'Discourse-Present: true' \
  -H 'DNT: 1' \
  -H 'X-CSRF-Token: …' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'User-Agent: …' \
  -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
  -H 'Accept: */*' \
  -H 'Referer: https://try.discourse.org/' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'sec-ch-ua-platform: "Linux"' \
  --data-raw 'login=demouser&password=demopassword&second_factor_method=1&timezone=America%2FToronto' \
  --compressed

وتكرار منطق تسجيل الدخول هذا في التطبيق.

على حد فهمي في هذه اللحظة، يبدو أن الطريقة المستخدمة في مثال React Native يمكن نقلها إلى تطبيق سطح المكتب الخاص بنا (وهو مكتوب بلغة Python).

نقطة الوصول إلى واجهة برمجة التطبيقات المستخدمة تبدو هي <site>/session، وهي تأخذ اسم مستخدم وكلمة مرور ورمز CSRF. يمكن الحصول على رمز CSRF من <site>/session/csrf.

هذا قريب جدًا مما كنت أبحث عنه. أعتقد أنني سأجرب ذلك، وسأبلغكم إذا نجح معي.

هل نقطة الوصول إلى واجهة برمجة التطبيقات <site>/session موثقة في أي مكان؟

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

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

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

تجربتي الشخصية مع هذا هي أن استخدام مفاتيح واجهة برمجة تطبيقات المستخدم هو خيار أكثر أمانًا وبساطة من محاولة استخدام نقاط نهاية الجلسة. :slight_smile:

إعجابَين (2)

إليك 20 سطرًا من كود بايثون تقوم بنفس الشيء تقريبًا مثل كود React Native المشار إليه بواسطة @renato (باستثناء عدم وجود توافق مع Discourse 2.5 - لا أحتاج إلى ذلك)

إنه يعمل بشكل جيد، بافتراض أنك تستخدم تسجيل الدخول الأساسي المستند إلى اسم المستخدم وكلمة المرور. سأبحث أيضًا في الطرق البديلة، باستخدام تسجيل الدخول Discourse SSO كما هو مهيأ في مثيل Discourse.

import requests
import json

def discourse_authenticate(url, name, password):
    session = requests.Session()
    session.headers.update({'X-Requested-With': 'XMLHttpRequest'})
    r1 = session.get(url + '/session/csrf')
    csrf_token = json.loads(r1.text).get('csrf')
    r2 = session.post(url + '/session',
        data={
            'login': name,
            'password': password,
            'authenticity_token': csrf_token,
        },
    )
    if r2.status_code != 200:
        return None
    return json.loads(r2.text)

لقد حاولت تطبيق هذا ولكن لم أتمكن من جعله يعمل. فيما يلي بعض أكواد Python (المبسطة) التي تنشئ عنوان URL لـ .../session/sso_provider. عندما أحاول، أحصل على Login Error. لا فكرة عما يعنيه ذلك.

import secrets
import base64
import urllib.parse
import hmac
import hashlib

forum_url = 'https://forum.embeetle.com'
target_url = 'https://embeetle.com/#account'
sso_secret = b'JCLSVcqbAnEPXz2p2xBY'

nonce = secrets.token_urlsafe()
payload = f'nonce={nonce}&return_sso_url={target_url}'
payload_base64 = base64.b64encode(payload.encode('utf-8')).decode()
payload_for_url = urllib.parse.quote(payload_base64)

payload_for_url = 'bm9uY2U9YklKeEU1WWw2OFhjSkJydGlwSU15UTRZeVlMeWd6ZzQyUU9mOFo0SWF5QSZyZXR1cm5fc3NvX3VybD1odHRwczovL2VtYmVldGxlLmNvbS8jYWNjb3VudA%3D%3D'

signature = hmac.new(
    sso_secret, payload_for_url.encode('utf-8'), hashlib.sha256
).hexdigest()

print(f'{forum_url}/session/sso_provider?sso={payload_for_url}&sig={signature}')

على سبيل المثال، قد يولد أحد التشغيلات عنوان URL في أمر curl أدناه:

johan@morla:~/sa> curl 'https://forum.embeetle.com/session/sso_provider?sso=bm9uY2U9YklKeEU1WWw2OFhjSkJydGlwSU15UTRZeVlMeWd6ZzQyUU9mOFo0SWF5QSZyZXR1cm5fc3NvX3VybD1odHRwczovL2VtYmVldGxlLmNvbS8jYWNjb3VudA%3D%3D&sig=a392ebb81b93ba7411290fbd00240921ae053bbb82998830dda994c8a71853da'
Login Errorjohan@morla:~/sa> 

بصفتك مسؤولاً، قم بتمكين “تسجيل اتصال الخطاب المطول”، جرب ذلك، ثم تحقق من /logs في منتداك لرؤية المزيد من الأخطاء التفصيلية، على سبيل المثال https://forum.embeetle.com/logs

سترى على سبيل المثال:

تحتاج إلى توقيع الحمولة، وليس الحمولة المقتبسة، على سبيل المثال:

signature = hmac.new(
  sso_secret, payload_base64.encode('utf-8'), hashlib.sha256
).hexdigest()

وبعد ذلك يعمل!

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

3 إعجابات

لا تقلق، الصفحة التي أعيد التوجيه إليها هي صفحة عامة، فقط للاختبار.

لقد قمت بتغيير السر على أي حال.

إعجابَين (2)

ما هي أفضل 3 اقتراحات لديك مفتوحة المصدر لهذه المهمة المحددة؟

أنا أستخدم Nginx ولكن ربما يمكن إدارة ذلك بتطوير أكثر قوة مثل Keycloak؟

أعني بـ auth-proxy هذا: GitHub - discourse/discourse-auth-proxy: An http proxy that uses the DiscourseConnect protocol to authenticate users

إعجابَين (2)

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.