دليل OAuth معاينة
معاينة — غير متاح بعد. هذه الصفحة تصف تصميم خادم التفويض قيد البناء حتى تتمكن من التخطيط لتكاملك. لا يمكن استدعاء أي من نقاط النهاية أدناه الآن، وقد تتغير التفاصيل قبل الإطلاق.
عنوان الخادم ($AH_AUTH_HOST) ومدد صلاحية الرموز تُنشر عند الإطلاق. حتى ذلك الحين استخدم مفاتيح API.
نظرة عامة
- OAuth 2.0 بتدفق رمز التفويض مع PKCE (
S256فقط). - الرموز معتمة (ليست JWT) ومُخزّنة مُجزّأة لدينا، فالإلغاء يسري فوراً. لا تحاول تحليلها.
- رمز الوصول مرتبط بثلاثة: تطبيقك، والشركة، والصلاحيات الممنوحة.
- تقبل
/v1الترويسةAuthorization: Bearer <token>إلى جانب مفاتيحah_.
| نقطة النهاية | الغرض |
|---|---|
GET /oauth/authorize | شاشة الموافقة في متصفح المستخدم (بالعربية والإنجليزية) |
POST /oauth/token | استبدال رمز التفويض، وتحديث الرموز (من خادمك) |
POST /oauth/revoke | إلغاء رمز (من خادمك) |
1. سجّل تطبيقك
في لوحة المطوّر تنشئ تطبيقاً داخل مؤسسة المطوّر الخاصة بك وتحصل على client_id وclient_secret. السرّ يظهر مرة واحدة ويمكنك تدويره. سجّل روابط إعادة التوجيه بدقة — المطابقة حرفية — واختر الصلاحيات التي يطلبها التطبيق. التطبيق الجديد في وضع التطوير ويتصل فقط بشركات التجربة الخاصة بمؤسستك.
2. أرسل المستخدم إلى رابط التفويض
أنشئ code_verifier عشوائياً لكل محاولة واحتفظ به في خادمك، واحسب منه code_challenge، وأرسل state عشوائياً وتحقق منه عند العودة.
import crypto from "node:crypto";
// 1. A fresh verifier per authorization attempt; keep it server-side.
const codeVerifier = crypto.randomBytes(32).toString("base64url");
const codeChallenge = crypto
.createHash("sha256")
.update(codeVerifier)
.digest("base64url");
const state = crypto.randomBytes(16).toString("base64url");
// 2. Send the user's browser here.
const url = new URL("/oauth/authorize", process.env.AH_AUTH_HOST);
url.search = new URLSearchParams({
response_type: "code",
client_id: process.env.AH_CLIENT_ID,
redirect_uri: "https://yourapp.example/callback/ahlan-hamad",
scope: "employees:read payroll:read",
state,
code_challenge: codeChallenge,
code_challenge_method: "S256",
}).toString();| المعامل | القيمة |
|---|---|
response_type | code |
client_id | معرّف تطبيقك |
redirect_uri | أحد الروابط المسجلة، حرفياً |
scope | صلاحيات مفصولة بمسافات، ضمن ما يطلبه التطبيق |
state | قيمة عشوائية تتحقق منها عند العودة |
code_challenge | BASE64URL(SHA256(code_verifier)) |
code_challenge_method | S256 |
يسجّل المستخدم الدخول إلى أهلاً حمد. مستخدم لديه صلاحية integrations.manage يختار الشركة، ويرى اسم تطبيقك والصلاحيات المطلوبة، ثم يوافق أو يرفض. نعيده إلى رابطك:
https://yourapp.example/callback/ahlan-hamad?code=…&state=…
https://yourapp.example/callback/ahlan-hamad?error=access_denied&state=…3. استبدل الرمز برموز
رمز التفويض صالح لاستخدام واحد ولمدة 60 ثانية. استبدله من خادمك مع نفس redirect_uri وcode_verifier.
curl -X POST "$AH_AUTH_HOST/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=authorization_code \
-d code="$CODE" \
-d redirect_uri="https://yourapp.example/callback/ahlan-hamad" \
-d code_verifier="$CODE_VERIFIER" \
-d client_id="$AH_CLIENT_ID" \
-d client_secret="$AH_CLIENT_SECRET"{
"access_token": "…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "…",
"scope": "employees:read payroll:read"
}قيمة expires_in في المثال توضيحية؛ مدد الصلاحية تُحدَّد عند الإطلاق.
4. استدعِ الـ API
curl https://actions.ahlanhamad.com/v1/company \
-H "Authorization: Bearer $ACCESS_TOKEN"نفس نقاط النهاية ونفس فحص الصلاحيات ونفس حدّ الطلبات ونفس أخطاء problem+json كما مع مفاتيح API. رمز ملغى أو منتهي يُرجع 401 unauthenticated.
5. حدّث الرموز
curl -X POST "$AH_AUTH_HOST/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=refresh_token \
-d refresh_token="$REFRESH_TOKEN" \
-d client_id="$AH_CLIENT_ID" \
-d client_secret="$AH_CLIENT_SECRET"- رموز التحديث تتجدد: كل تحديث يُرجع رمز تحديث جديداً ويُبطل القديم. احفظ الجديد قبل استخدام رمز الوصول.
- كشف إعادة الاستخدام: تقديم رمز تحديث سبق استخدامه يُلغي سلسلة الرموز كلها لهذا الاتصال، ويجب أن يوافق العميل من جديد. احرص على أن يحدّث عامل واحد فقط في كل مرة.
- يمكن طلب صلاحيات أقل مما مُنح عند التحديث، ولا يمكن طلب أكثر.
6. الإلغاء
curl -X POST "$AH_AUTH_HOST/oauth/revoke" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d token="$REFRESH_TOKEN" \
-d client_id="$AH_CLIENT_ID" \
-d client_secret="$AH_CLIENT_SECRET"ألغِ الرموز عندما يفصل العميل حسابه من منتجك. يستطيع العميل أيضاً إلغاء تطبيقك من صفحة التطبيقات المتصلة؛ عندها تتوقف الرموز فوراً ويُعطَّل الويب هوك الخاص بهذا الاتصال.
الصلاحيات
نفس صلاحيات مفاتيح API. GET /v1/company لا يحتاج صلاحية. اطلب أقل ما يحتاجه تكاملك — العميل يرى القائمة قبل الموافقة.
| الصلاحية | تسمح بـ |
|---|---|
employees:read | عرض الموظفين وقراءتهم |
payroll:read | عرض مسيّرات الرواتب المغلقة وقراءتها (الإجماليات والقيد فقط) |
attendance:read | قراءة الحضور |
attendance:write | إرسال حركات الحضور والانصراف |
webhooks:manage | تسجيل نقاط الويب هوك وإدارتها |
لا يوجد أي مسار — مفتاح أو OAuth — يُرجع رواتب أو بدلات الموظفين الفردية.
الأخطاء
أخطاء /oauth/token و/oauth/revoke تتبع صيغة OAuth القياسية (RFC 6749 §5.2): error وerror_description. أخطاء رابط التفويض تُعاد إلى redirect_uri كمعاملات استعلام، إلا إذا كان الرابط نفسه أو client_id غير صالح، فتظهر للمستخدم ولا يُعاد توجيهه.
{
"error": "invalid_grant",
"error_description": "The authorization code has expired or was already used"
}error | المعنى |
|---|---|
invalid_request | معامل ناقص أو مكرر، أو رابط إعادة التوجيه لا يطابق حرفياً رابطاً مسجلاً للتطبيق. |
invalid_client | معرّف عميل غير معروف أو سرّ عميل خاطئ. |
invalid_grant | انتهت صلاحية الرمز (60 ثانية) أو استُخدم من قبل أو صدر لعميل أو رابط آخر؛ أو مُتحقق PKCE لا يطابق؛ أو رمز التحديث استُخدم من قبل أو أُلغي. |
invalid_scope | صلاحية غير موجودة، أو أكثر مما طلبه التطبيق أو مُنح للاتصال. |
unauthorized_client | لا يحق للتطبيق الاتصال بهذه الشركة — مثل تطبيق في وضع التطوير وشركة ليست من شركات التجربة الخاصة بك. |
unsupported_grant_type | قيمة grant_type غير authorization_code أو refresh_token. |
access_denied | تُعاد إلى رابط إعادة التوجيه عندما يرفض المستخدم. |