مدى إمكانية السماح لعميل مفتاح API للمستخدم بالتسجيل لتوجيه المصادقة الصحيح

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

الوظائف الحالية

حاليًا، يجب تسجيل عمليات إعادة التوجيه لمفتاح واجهة برمجة تطبيقات المستخدم بواسطة الموقع المضيف في إعداد الموقع allowed_user_api_auth_redirects. يجب التحقق من أي auth_redirect يتم إرساله مع طلب إنشاء مفتاح مقابل قائمة إعدادات الموقع هذه (انظر هنا). هذا إجراء وقائي معقول لتجنب إعادة التوجيه المفتوحة (التي تؤدي إلى مخاطر أمنية مختلفة).

السبب الفعال

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

يعمل هذا حاليًا مع Mastodon لأن كل خادم Mastodon هو موفر OAuth يسمح بالإنشاء البرمجي لعملاء OAuth. يتدفق الأمر على النحو التالي:

  1. يحدد المستخدم نطاق Mastodon الذي يوجد عليه حسابه.
  2. إذا كانت هذه هي المرة الأولى التي يتم فيها التفويض على هذا النطاق، يقوم المكون الإضافي بإنشاء تطبيق OAuth على خادم Mastodon هذا، وتسجيل عمليات إعادة التوجيه الخاصة به والحصول على بيانات اعتماد العميل لتدفق OAuth.
  3. يقوم المكون الإضافي بتنفيذ تدفق OAuth مع المستخدم باستخدام تطبيق OAuth الذي أنشأه (أو أنشأه سابقًا) في 2.

الهدف هو الحصول على وظائف مماثلة تمامًا مع Discourse باستخدام مفاتيح واجهة برمجة تطبيقات المستخدم. تم تنفيذ هذا بالفعل في هذا الطلب المدمج (PR)

يتطلب هذا التدفق أن يكون الموقع المضيف قد أضاف بالفعل نطاق العميل أو إعادة توجيهه إلى allowed_user_api_auth_redirects.

التغيير المحتمل

ما أفكر فيه حاليًا هو إنشاء طلب مدمج (PR) إلى discourse/discourse سيقوم بما يلي:

إنشاء جدول user_api_key_client

الأعمدة:

  • client_id و application_name تم ترحيلهما من user_api_key
  • redirect_uri (اختياري)
  • public_key (اختياري)

ستعمل جميع الوظائف الحالية التي تستخدم client_id و application_name كما كان من قبل، من خلال user_api_key_client.

إضافة مسار تسجيل العميل

post "/user-api-key/register" => "user_api_keys#register"

المعلمات المطلوبة:

  • application_name
  • client_id
  • public_key
  • auth_redirect

الإجراء:

  • التحقق من صحة المعلمات وحفظها في user_api_key_client
  • إرجاع رمز نجاح إذا نجح

السماح باستخدام العملاء المسجلين في إجراءات الإنشاء

تغيير إجراء create في UserApiKeyController على النحو التالي:

  • إذا كان client_id موجودًا في user_api_key_client ولديه كل من auth_redirect و public_key:
    • التحقق من صحة استخدام auth_redirect مع auth_redirect المخزن
    • استخدام public_key المخزن لتشفير حمولة الإرجاع
  • بخلاف ذلك، اتبع الوظائف الحالية.

مع @pmusaraj

إعجابَين (2)

بشكل عام، أنا مع هذا لأنه سيمكن سير عمل تفويض المستخدم في المكون الإضافي ActivityPub وما بعده دون الكثير من الاحتكاك للمسؤولين.

بعض الأسئلة رغم ذلك:

أنا لست من أشد المعجبين بالترحيل هنا، أفضل ترك مفاتيح واجهة برمجة التطبيقات الحالية للمستخدمين كما هي لأن معرف واسم مفاتيح المستخدم الفردية مستقلة عن معرف واسم العملاء المسجلين. ربما يمكننا بدلاً من ذلك إضافة عمود إلى user_api_key لـ user_api_key_client_id. يمكن للمفاتيح المرتبطة بالعملاء بعد ذلك استخدام إعادة التوجيه التي تم تكوينها بواسطة العميل (والمفاتيح الحالية، بالطبع، تحتفظ بالسلوك الحالي).

علاوة على ذلك، هل يجب أن يكون المسؤولون قادرين على مراجعة قائمة العملاء المسجلين في مكان ما؟

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

لهذا السبب أعتقد أنه يجب ترحيل client_id :slight_smile:

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

# تدمير أي مفاتيح قديمة كانت لدينا
UserApiKey.where(user_id: current_user.id, client_id: params[:client_id]).destroy_all

key =
  UserApiKey.create!(
    application_name: @application_name,
    client_id: params[:client_id],
    user_id: current_user.id,
    push_url: params[:push_url],
    scopes: scopes.map { |name| UserApiKeyScope.new(name: name) },
  )

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

بالفعل، هذا القيد 1:1 هو سبب عدم نجاح النهج الذي تقترحه على الأرجح

لكي يقوم العميل بتسجيل إعادة توجيه لعدة مفاتيح، يجب أن يكون تفرد client_id مستقلاً عن المفاتيح نفسها. وإلا فلن يعمل التسجيل لعدة مفاتيح لأن client_id في إجراء التسجيل هو ما يستخدم لتحديد إعادة التوجيه.

إذا قمت بنقل client_id و application_name إلى جدول user_api_key_clients المخصص، فإنك تحتفظ بحالات 1:1، ولكنك تسمح أيضًا بحالات 1:متعدد، والميزات التي تفتحها، مثل تسجيل redirect_uri لأغراض ActivityPub.

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

عذرًا على التأخير يا أنجوس.

أرى ما تقوله، ولكن من خلال ترحيل client_id الحالي، سنحتفظ ببعض هذا الالتباس في الجدول الجديد لأن المعرفات/الأسماء التي تم ترحيلها ستكون للمفاتيح التي هي عملاء 1 إلى 1. خاصة من منظور المسؤول على المدى الطويل، من الجيد أن يكون لديك قائمة بالعملاء المسجلين المتعددين إلى واحد.

ولكن ربما معالجة ذلك ليست مناسبة في هذا الوقت.

لنتابع الخطة التي تقترحها، نتطلع إلى طلب السحب (PR). شكرًا!

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

لقد نشرت مسودة طلب سحب (PR) لتنفيذ هذا

لاحظ أن:

  • جميع الوظائف الحالية تعمل كما كانت من قبل.
  • يمكن التراجع عن الترحيل.

للإنجاز:

  • إصلاح الاختبارات الفاشلة.
  • حاليًا يمكن لأي مستخدم تسجيل عميل. هل يجب تقييد هذا بطريقة ما (؟)
إعجاب واحد (1)

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

أثناء إعادة البناء، لاحظت أن فصل المفاتيح عن العملاء كما يفعل طلب السحب هذا سيحل أيضًا مشكلات مثل تلك التي عالجها @nat مؤخرًا.

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

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

تم دمج هذا أخيرًا، شكرًا جزيلاً لك @angus، نأمل أن يزيل هذا العوائق عنك الآن.

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

شكراً جزيلاً! لقد (أزال عني العائق) :slight_smile: سيكون هناك تطبيق في طلب سحب (pull request) للمصادقة بين خوادم Discourse باستخدام ActivityPub قريباً.

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