<div data-theme-toc="true"> </div>
يحتوي Discourse على نظام لتوليد مفاتيح واجهة برمجة التطبيقات (API) **لكل مستخدم** إذا تم اتباع بروتوكول محدد للغاية. تسهل هذه الميزة وصول "التطبيقات" إلى مثيلات Discourse دون الحاجة إلى إشراك المشرفين.
### وصف شامل
على مستوى عالٍ:
1. يقوم العميل (تطبيق سطح المكتب، أو إضافة المتصفح، أو تطبيق الهاتف المحمول) بإنشاء زوج مفاتيح خاص/عام وعنوان URL لإعادة التوجيه
2. يعيد العميل التوجيه إلى مسار على Discourse مع تقديم المفتاح العام الخاص به إلى Discourse
3. يحصل Discourse على موافقة المستخدم لاستخدام التطبيق
4. يقوم Discourse بإنشاء مفتاح API خاص بالمستخدم
5. يعيد Discourse التوجيه إلى عنوان URL لإعادة التوجيه مع حمولة مشفرة باستخدام المفتاح العام تحتوي على مفتاح API الخاص بالمستخدم
### التفاصيل
حالات الاستخدام:
1. تطبيقات سطح المكتب التي تستعلم عن مواقع Discourse نيابة عن المستخدمين النهائيين للحصول على عدد الإشعارات عبر مواقع متعددة.
2. تطبيقات الهاتف المحمول التي تستعلم عن مواقع Discourse نيابة عن المستخدمين النهائيين وتتعامل مع الإشعارات اللحظية (push notifications).
3. تطبيقات الويب التي توفر لوحة معلومات للمستخدمين النهائيين حول مواقع Discourse المختلفة.
4. عمليات تكامل مخصصة مع تطبيقات الطرف الثالث التي تستهلك Discourse كجزء من تطبيق شركة عام. مثال: دمج إشعارات مجتمع Discourse في تطبيق hopscotch.
التصميم:
### إعدادات الموقع
- **allow_user_api_key_scopes**: نطاقات الوصول المسموح بها لمفاتيح API الخاصة بالمستخدم. يتم تعريف النطاقات [هنا](https://github.com/discourse/discourse/blob/main/app/models/user_api_key_scope.rb). النطاقات المضمنة المتاحة هي: `read`، `write`، `message_bus`، `push`، `one_time_password`، `notifications`، `session_info`، `bookmarks_calendar`، `user_status` (قد تسجل المكونات الإضافية نطاقات إضافية).
- **user_api_key_allowed_groups**: يتحكم في المجموعات المسموح لها بإنشاء مفاتيح API للمستخدم (افتراضيًا المسؤولون، والمشرفون، ومستوى الثقة 0)
- **allowed_user_api_push_urls**: قائمة المواقع التي يمكن أن تكون أهدافًا للإشعارات اللحظية
- **allowed_user_api_auth_redirects**: وجهات إعادة التوجيه المسموح بها بعد إنشاء مفتاح API للمستخدم
### الإعدادات العامة
- **max_user_api_reqs_per_minute**: 20
- **max_user_api_reqs_per_day**: 2880
### عناصر تجربة المستخدم (UX)
إذا تم منح أي مفاتيح API للمستخدم، يعرض Discourse علامة تبويب **apps** (التطبيقات) في صفحة المستخدم.
تعرض علامة التبويب **apps** ما يلي:
- اسم التطبيق مثل: ("Discourse Notifier")
- تاريخ آخر استخدام
- تاريخ الموافقة
- قائمة بنطاقات الوصول الممنوحة
- زر **revoke access** (إلغاء الوصول) حتى تتمكن من إلغاء أي مفاتيح بسهولة
#### واجهة مستخدم تفويض مفتاح API
يجب أن يوافق المستخدمون النهائيون صراحةً على كل مفتاح في صفحة تشرح بوضوح ما يحدث، على سبيل المثال:
> يطلب "Discourse Notifier" الوصول التالي إلى حسابك:
> - قراءة الإشعارات ومسحها
> - قراءة معلومات جلسة المستخدم
> - إنشاء رمز تسجيل دخول لمرة واحدة
>
> [Authorize] (تفويض)
### تدفق توليد مفتاح API
تتطلب واجهة برمجة التطبيقات طلب GET واحدًا فقط من جانب المستخدم.
> :exclamation: اعتبارًا من Discourse 2.1، تنتهي صلاحية مفاتيح API للمستخدم هذه تلقائيًا إذا تُركت دون استخدام لفترات طويلة. يتم تعيين إعداد الموقع: `revoke user api keys unused days` على 180 بشكل افتراضي.
المعلمات:
* **auth_redirect**: عنوان URL لإعادة التوجيه إليه بالرمز المميز الذي تم إنشاؤه
* **application_name**: اسم التطبيق الذي يقوم بالطلب (سيتم عرضه في علامة تبويب "التطبيقات" في حساب المستخدم)
* **client_id**: مُعرّف فريد للعميل
* **nonce**: رقم عشوائي فريد تم إنشاؤه بواسطة العميل. سيتم عكسه في الحمولة المشفرة حتى يتمكن العميل من التحقق من مصداقية الاستجابة
* **scopes**: قائمة مفصولة بفواصل بنطاقات الوصول المسموح بها للمفتاح، راجع `allow user api key scopes` للحصول على القائمة الكاملة للنطاقات المتاحة
* **push_url**: عنوان URL لدفع الإشعارات إليه (مطلوب وصالح فقط إذا تم تضمين `push` أو `notifications` في النطاقات)
* **public_key**: الجزء العام من زوج المفاتيح الذي أنشأه العميل
* **padding** (اختياري): وضع حشو RSA المستخدم لتشفير الحمولة. القيم المقبولة هي `pkcs1` (افتراضي) أو `oaep`. يوصى باستخدام OAEP للتطبيقات الجديدة.
بعد استدعاء `/user-api-key/new` بالمعلمات الصحيحة، قد يحدث شيئان:
1. إذا لم يكن المستخدم مسجلاً دخوله، فسنقوم بإعادة التوجيه إلى تسجيل الدخول (بعد تسجيل الدخول سنستأنف التفويض)
2. بمجرد تسجيل دخول المستخدم، سيتم عرض واجهة مستخدم التفويض
بعد السماح بالتفويض، سيقوم النظام بإعادة التوجيه إلى عنوان URL المحدد في `auth_redirect` ويتضمن معلمة `payload` مشفرة تحتوي على كائن JSON مع مفتاح API الخاص بالمستخدم الذي تم إنشاؤه (`key`)، و`nonce`، وحالة الدفع (`push`)، وإصدار واجهة برمجة التطبيقات (`api`). إذا تم طلب نطاق `one_time_password`، فسيتم أيضًا تضمين معلمة استعلام `oneTimePassword` مشفرة بشكل منفصل. لا يتم عكس `client_id` لمزيد من الأمان.
### التحقق من إصدار واجهة برمجة التطبيقات (API version)
يتم ترقيم مفتاح API في Discourse. يمكن للعملاء التحقق من إصدار API لموقع Discourse عن طريق إجراء طلب HEAD إلى `https://sitename.com/user-api-key/new`. ستحتوي الاستجابة على رأس يسمى Auth-Api-Version يحتوي على رقم إصدار API الخاص بالموقع.
### استهلاك واجهة برمجة التطبيقات (Consuming the API)
سيكون استهلاك واجهة برمجة تطبيقات العميل مختلفًا إلى حد ما عن واجهة برمجة تطبيقات المسؤول الحالية.
يمكن للعميل تحديد رأسين:
`User-Api-Key` (مطلوب): المفتاح الذي تم إنشاؤه
و
`User-Api-Client-Id` (اختياري): قم بتوفير هذا لتحديث "معرف العميل" المخزن لهذا api_key في قاعدة البيانات.
بمجرد تحديد هذه الرؤوس، يمكن للعميل إجراء طلبات ضد واجهة برمجة التطبيقات تمامًا كما يفعلون عادةً.
### إنشاء كلمة مرور تسجيل دخول لمرة واحدة
اعتبارًا من الإصدار 4، تتضمن واجهة برمجة التطبيقات نطاقًا خاصًا: نطاق `one_time_password`، والذي يسمح للعملاء باستخدام مفتاح API الخاص بالمستخدم لإنشاء كلمة مرور لمرة واحدة. إذا قام العميل بتضمين هذا النطاق عند إنشاء مفتاح API باتباع الخطوات المذكورة أعلاه، فسيتم تضمين `oneTimePassword` مشفر كمعلمة استعلام منفصلة في إعادة التوجيه إلى العميل.
بدلاً من ذلك، يمكن للعميل إجراء طلب GET إلى `/user-api-key/otp` مع المعلمات التالية:
- auth_redirect
- application_name
- public_key
- padding (اختياري)
ومع ترويسة `User-Api-Key`.
سيؤدي هذا الطلب إلى إعادة التوجيه إلى شاشة في Discourse ستطلب من المستخدم السماح للتطبيق بالوصول إلى الموقع. إذا وافق المستخدم، فسيقوم الموقع بإعادة التوجيه إلى عنوان URL المحدد في `auth_redirect` وتضمين معلمة `oneTimePassword` مشفرة تحتوي على كلمة مرور لمرة واحدة يمكن للعميل استخدامها لتسجيل الدخول إلى الموقع عن طريق طلب `https://sitename.com/session/otp/ONE-TIME-PASSWORD`. (كلمة المرور لمرة واحدة صالحة لمدة 10 دقائق فقط).
### إلغاء مفاتيح API
لإلغاء مفتاح API، قم بإجراء طلب POST باستخدام ترويسة `User-Api-Key` وبدون معلمات إلى `/user-api-key/revoke`.
---
*آخر مراجعة بواسطة @SaraDev في [date=2022-07-12 time=17:00:00 timezone="America/Los_Angeles"]*
There are places I’ve strongly considered writing a delayed post tool, so I can compose a bunch of “word of the day” type things to keep going while I’m on vacation. Doing it without proper API access and pretending to be a browser seems somewhat more complicated than on other forum software.
That is a good example, but keep in mind, our default will be only to enable read tokens, not write ones. Site admins will have to opt to allow write tokens.
Completely agree that the _t cookie hacks are a huge problem.
Okay, but you have to have admin access to see that page yes? And as an admin, it seems I can only create 1 key, so can’t create many keys for different users. confused.
What are you trying to accomplish? It’s not clear because there is this (user api keys) and regular API tokens (which is what I think you are after) that admins can create for multiple users, but you have to do that from the individual user’s page inside of the admin dashboard by clicking on the “generate” button on the “API Key” field.
Hey everyone I’m not sure if this was resolved? I see that it’s possible to create an “All Users” and (per user) level API token as an admin, but I’m interested in giving a user the power to generate his/her own token. Has there been work done on this? It sounds like the original thread was getting at this idea, and then it was lost. Thanks!
Download the mobile App and then add a site, that uses the user api key system you have to follow a very strict workflow, no plans to expose arbitrary generation of keys in user prefs
Thank you! I downloaded the app, and then realized that the sites I belong to don’t have this enabled (I’ve been testing on my local machine with the Dockerized discourse). Just to make sure we are talking about the same thing - I’m interested in generating tokens to use just a scoped subset of functions (and not global API keys to do all the things). Is this what you are talking about?
It seems like, given that there is an endpoint to generate tokens, it would be logical to provide this function (to users with a certain trust level, for example) from within the site. Otherwise, it would need to be the case that the site generates some external page (with a server to hide an admin token) to generate the keys for the user. Is it the case that 1. there is no internal generation of tokens for the user (and why not?) and 2. Nobody has created some external app (javascript, flask, anything really) to perform this action?
This is tricky to consume cause you need to use custom HTTP headers (by design)
It would be very hard to educate even TL3 users about what the point is of this thing.
I prefer not to ship UI for this in core, but maybe you should write a plugin for your specific use case?
Can you explain a bit more about the “why” here?
The design of the system centers around “I have an external dedicated program”, “this program knows how to follow Discourse protocol”, “It asks for token”
API keys (non user ones) are much easier to consume cause you just append them after the ?
Can I pass the API key generated from the user page on this? I was trying to use that API key and seeing ‘You are not permitted to view the requested resource.’ error on /categories.json API request
عذراً إذا كان هذا تكراراً، لكنني أواجه صعوبة في استيعاب الخطوات المذكورة، رغم أنها مُنظمة بشكل ممتاز.
لدي تثبيت لـ Discourse على https://forum.domain.com وموقع على https://development.domain.com، وأحتاج من خلاله إلى إجراء مكالمات لتثبيت Discourse لجلب بعض البيانات وتحديد بعضها.
جميع الطلبات تعمل بنجاح من Postman باستخدام Api-Username وApi-Key دون أي مشكلة.
لكن في حالة طلبات Cross-Origin باستخدام JavaScript، لا يسمح Discourse باستخدام Api-Username، مما دفعني إلى اتباع المسار الموصوف في هذا الموضوع، أي استخدام User-Api-Key وUser-Api-Client-Id.
أحتاج بشكل أساسي إلى وصف للمعاملات PUBLIC_KEY وNONCE وCLIENTID المستخدمة في الطلب النموذجي أدناه، وإلى أين يمكنني الحصول عليها…
لحظة واحدة، هل هذا أمر خاص بكل مستخدم؟ هل تسمح لمستخدمين عشوائيين بفعل ذلك؟
يدعم واجهة برمجة التطبيقات (API) الخاصة بخادمنا الآن المصادقة القائمة على الرؤوس، لذا يمكنها العمل مع CORS تمامًا كما تفعل مفاتيح API الخاصة بالمستخدمين. يمكنك استخدام مفاتيح API الخاصة بالمستخدمين إذا كنت ترغب في تقييد النطاقات والسماح للمستخدمين النهائيين بإنشاء المفاتيح بدلاً من المسؤولين.
أعتقد أن كل مستخدم لا يحتاج إلى مفتاح خاص به… يجب أن يكون مفتاح إداري واحد كافيًا لما أحتاجه.
يمكنني استهلاك الـ API دون مشكلة عبر Postman. على سبيل المثال، طلب GET إلى /notifications.json?username=alanmurphy يعيد البيانات دون مشكلة باستخدام api-key فقط كعنوان.
إذا قمت بتفعيل هذا الطلب من وحدة تحكم تثبيت Discourse، فسأحصل على البيانات دون مشكلة أيضًا، أي:
var xhr = new XMLHttpRequest();
xhr.addEventListener(“readystatechange”, function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open(“GET”, “https://**********.com/notifications.json?username=alanmurphy”);
xhr.setRequestHeader(“api-key”, “d06ca53322d1fbaf383a6394d6c229e56871342d2cad953a0fe26c19df7645ba”);
xhr.setRequestHeader(“api-userame”, “system”);
xhr.send();
كل شيء على ما يرام:+1:
ومع ذلك، إذا قمت بذلك من النطاق الفرعي الذي أود من خلاله الاتصال بـ Discourse، فإن النظام يخبرني بأنه تم حظره بسبب سياسة CORS: حقل الرأس api-key غير مسموح به بواسطة Access-Control-Allow-Headers.