مواصفات مفاتيح API للمستخدم

I find allowed_user_api_auth_redirects default of “discourse://auth_redirect” rather restrictive, especially because “discourse” does not appear to be a valid URI scheme.

Please explain the thinking behind this default. Thank you.

I am having this issue as well. If I initiate the API from a JS application, then automatically the allowed headers are: User-Api-Key, User-Api-Client-Id even though I do not need user API keys. All I want is a simple API key but I cannot get anything to work. If I try to pass Api-Key in the headers I get a CORS error since it expects User-Api-Key. But when I try to use User-Api-Key, I get 403 errors. I am stuck. I would think this is the base usage for using the APIs. I am not trying to do anything out of the ordinary. I am simply trying to create a new topic post.

إعجابَين (2)

That is the custom URI scheme used by the DiscourseHub app for iOS and Android.

6 إعجابات

I’ve got a question concerning the “read tokens” and “write tokens”. This comment here is from 2016, so this possibly had already been changed? Or are the defaults still only “read tokens”?

Background: I’m one of the coders behind a distributed social media system. We already do have connectors to non-federating systems. The idea is to write an addon for discourse as well. But when most likely most system won’t allow users to generate tokens that allow posting, we will try another way. We already do have a mail connector. Then we will simply use the mailing list function of Discourse and we will try to enhance the returned content and will post via SMTP.

You can do write tokens if you ask for the scope upfront

3 إعجابات

Of course this is always possible. But I have the feeling that this is a support nightmare. Our software has got some hundred installations with (in total) more than 10k users. When they see that there is an addon that is connection to Discourse, many will surely like to use it. And since it most likely won’t work out of the box, this will generate questions and support work from our side. Additionally it will generate work for the admins of the several Discourse installations. And very likely not all will allow it - which will cause frustration.

So possibly at first I will focus on integrating the mailing list mode mails. Or is it possible to combine these two? Means: Reading of the posts via the API, but posting via SMTP?

Hi…I don’t know to generate public_key… should I use RSA generator to get public/private key?
If so I have done with some online RSA generators. but I am getting this error:

OpenSSL::PKey::RSAError (Neither PUB key nor PRIV key: nested asn1 error) /var/www/discourse/app/controllers/user_api_keys_controller.rb:189:in `initialize'

Also, I want to ask you guys if this suits my user case:
I have an app, and I want to basically authenticate user and get the username, is generating api key flow the simplest flow for me to validate user’s login in my app? If possible, I want avoid SSO because it seems more complicate.

Same boat here, although I am only trying to use User-Api-Key (not Api-Key) to create a topic post and am getting CSRF denial from the actionpack library.

Unless the discourse server has turned off CSRF checking, posting from a third-party desktop app seems hard. I’m not about to emulate a browser.

@sam What is your take on allowing User API Keys that only have the read scope attached, to be passed via URL params on GET requests?

Use case is allowing integrations like subscribing your Improved Bookmarks with Reminders in Google Calendar using User API keys.

5 إعجابات

How about creating a specific new scope, with a third parameter to indicate “get param allowed”. That way, people can’t misuse it for other things (e.g. bypassing CORS and requesting the discourse API from another site).

(from here)

SCOPES = {
    read: [:get],
    write: [:get, :post, :patch, :put, :delete],
    message_bus: [[:post, 'message_bus']],
    push: nil,
    one_time_password: nil,
    notifications: [[:post, 'message_bus'], [:get, 'notifications#index'], [:put, 'notifications#mark_read']],
    session_info: [
      [:get, 'session#current'],
      [:get, 'users#topic_tracking_state'],
      [:get, 'list#unread'],
      [:get, 'list#new'],
      [:get, 'list#latest']
    ],
+   calendar: [ [:get, 'users#bookmarks_cal', true ] ],
  }

(Aside: why are we using nested arrays here…)

10 إعجابات

I like that the API key would be flagged explicitly as “allowed in GET” at the user level.

As a whole the option could be open for any GETs. The rule I like is, when operating in this mode:

  1. User API key is 100% restricted to a single specific GET controller action
  2. User API key is flagged as allowed in GET query params.

This limits the impact of any leak here via a proxy cause the key will never be reused.

I guess {get: 'list#new'} , {get: 'list#latest'} would work as well.

7 إعجابات

I’m super interested in get param only type user api keys. My question is, are you guys planning to allow people to generate these keys via UI?

Probably, maybe behind a site setting or with a plugin. We do plan to normalise the feature set a bit so admin api keys also support scopes.

4 إعجابات

Hi…Are you able to resolve this issue? I have the same issue and not able to fix it. I tried passing different type of keys and nothing worked. Any help would be greatly appreciated.

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

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

هل توجد طريقة للقيام بـ OAuth 2 فقط مع Discourse كمزود OAuth؟

إعجابَين (2)

هل نجحت في ذلك باستخدام مفتاح API الخاص بالمستخدم؟ أنا أيضًا أحصل على رسالة “غير مصرح لك بعرض المورد المطلوب”

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

لقد اكتشفت الخطأ الذي ارتكبته: الحمولة المُرجعة ليست مفتاح UserAPI نفسه، بل هي سلسلة JSON مشفرة، ويتطلب فك تشفيرها استخدام المفتاح الخاص من زوج المفاتيح الخاص/العامة.

إعجابَين (2)

تعديل: تمكنت من جعل معظمه يعمل، وسأقدم وصفًا بمجرد أن أتمكّن من تشغيله بالكامل.


كيف يحصل العميل على زوج المفاتيح الخاص/العام والمعرف؟

هل يمكنك توفير كود للحصول على مفتاح API للمستخدم باستخدام تطبيق جافا سكريبت؟ (تطبيق جافا سكريبت يحاول السماح للمستخدم بإجراء مكالمات API إلى منتدى Discourse).

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

أعتقد أن المشكلة قد تكون في كيفية توليد زوج المفاتيح الخاص/العام (كيف يتم ذلك؟)، ثم معالجة إعادة التوجيه.

أي كود سيكون موضع تقدير.

تمكنت من جعل هذا يعمل بعد بعض التجربة والخطأ.

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

لنفعل ذلك، أحتاج إلى إنشاء رمز API خاص بكل مستخدم لإجراء الاستدعاءات نيابة عن كل مستخدم محدد (على الأقل في بيئة Node.js/JavaScript).


ملاحظة: بالنسبة لجهة JavaScript، وجدت أن الكود الذي قدمه @KengoTODA هنا مفيد جدًا: discourse-api-key-generator/src/index.ts at main · KengoTODA/discourse-api-key-generator · GitHub


إليك الخطوات التي اتبعتها:

أولاً: توليد زوج من المفاتيح العامة والخاصة.

هذا شيء يجب أن يولده تطبيقك — مفتاح عام ومفتاح خاص. توفر ملخص GitHub (Gist) طريقة واحدة للقيام بذلك.

ثانياً: وجود عنوان URL لإعادة التوجيه.

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

لاحظ أن عنوان URL لإعادة التوجيه يجب أن يُدرج في القائمة البيضاء في إعدادات الموقع لموقع Discourse المستهدف.

كما يحتاج موقع Discourse على الأرجح إلى تفعيل إعداد الموقع “السماح بمفاتيح API للمستخدمين”. راجع المنشور الأصلي في هذا الموضوع بخصوص “إعدادات الموقع”.

ثالثاً: إرسال استدعاء طلب API إلى عنوان URL لطلب Discourse.

لذا، سيقوم تطبيقك بإرسال استدعاء إلى عنوان URL يتبع هذا الشكل:

https://[your target discourse site .com]/user-api-key-new"

مع إضافة المعاملات التالية:

  • اسم تطبيقك
  • “client_id” الخاص بك (تمكنت من استخدام hostname()، من const {hostname} = require('os') لتطبيق سطح المكتب، تمامًا كما في ملخص GitHub المشار إليه أعلاه)
  • النطاقات (scopes) (هذه هي النطاقات التي تريد أن يتمكن المستخدم من القيام بها عبر API، مثل “write”، “read”، إلخ)
  • مفتاحك العام (من الخطوة 1 أعلاه)
  • عنوان URL لإعادة التوجيه الخاص بك (من الخطوة 2 أعلاه)
  • nonce (هذه قيمة يمكنك اختيارها — يبدو أن استخدام ‘1’ فقط يعمل)

رابعاً: موافقة المستخدم على تطبيقك في صفحة موقع Discourse التي يتم فتحها بواسطة عنوان URL للطلب.

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

في تلك الصفحة، يوجد زر يسمح للمستخدم بالموافقة. عند النقر على هذا الزر، يعيد موقع Discourse التوجيه إلى عنوان URL لإعادة التوجيه الذي قدمته، ويضيف كمعامل ?payload=[the API KEY]. مفتاح API هنا هو المفتاح الذي تحتاج إلى فك تشفيره في تطبيقك.

خامساً: يلتقط تطبيقك قيمة عنوان URL لإعادة التوجيه (مع قيمة الحمولة)، وتقوم بفك تشفير مفتاح API.

لقد اقتربت من النهاية. يحتاج تطبيقك إلى تحليل عنوان URL لإعادة التوجيه الذي انتقل إليه Discourse، والحصول على مفتاح API الموجود في الحمولة.

بمجرد حصولك على مفتاح API هذا، تحتاج إلى القيام بأمرين:

  1. احصل على المفتاح الفعلي، وليس النسخة المشفرة URL: إذا كنت تحصل على معامل من عنوان URL، فغالبًا ما يكون مشفرًا URL (إضافة % هنا وهناك، إلخ). تحتاج إلى تنظيفه. في JavaScript، وجدت أن decodeURIComponent تعمل لهذا الغرض.
  2. بمجرد استلامك لمفتاح API المنقى من Discourse، تحتاج إلى فك تشفيره. للقيام بذلك، يمكنك استخدام فك التشفير في JavaScript باستخدام المفاتيح الخاصة. أساسًا، تستخدم مفتاحك الخاص (المُولد في الخطوة الأولى أعلاه) لفك تشفير مفتاح API المنقى. هناك بعض أمثلة JavaScript في ملخص GitHub الذي أشرت إليه أعلاه: discourse-api-key-generator/src/index.ts at main · KengoTODA/discourse-api-key-generator · GitHub

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

سادساً: استخدم الرمز (أي مفتاح API النهائي، المنقى، وفك تشفيره) لإجراء استدعاءات API نيابة عن المستخدم.

مع هذا الرمز، يبدو أنك لا تحتاج إلى إدخال اسم المستخدم في استدعاء API. أجد أن العنوان التالي كافٍ عند تضمينه في استدعاءات GET أو POST أو PUT، إلخ:

headers: {
"User-Api-Key": [the token]
}

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

7 إعجابات

ما هي الآثار الأمنية لإضافة أشياء إلى allowed_user_api_auth_redirects؟ لدي شخص يطلب إضافة سلسلة نصية لدعم تكامل NextCloud.

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