Authagonal

التوثيق

كل ما تحتاجه للبدء مع Authagonal — من إنشاء أول مستأجر لك إلى ربط SSO وSCIM والعلامة التجارية المخصصة.

البدء

يمنح Authagonal كل مستأجر خادم OIDC متوافقًا تمامًا مع المعايير. يحصل كل مستأجر على عنوان URL خاص بالمُصدِر، ووثيقة اكتشاف، ونقاط نهاية للرموز، دون أي بنية تحتية مشتركة بين المستأجرين. يمكنك الانتقال من الصفر إلى تدفق تسجيل دخول يعمل بالكامل في أقل من 5 دقائق.

إنشاء حساب

سجّل في authagonal.io واختر معرّفًا (slug) لحسابك. يصبح هذا المعرّف نطاق المُصدِر الخاص بك: {slug}.authagonal.io. بعد إنشاء حسابك، تحقق من عنوان بريدك الإلكتروني للبدء.

Authagonal signup page showing tenant slug input and email verification

اختر معرّفًا فريدًا لحسابك أثناء التسجيل

تسجيل عميل

انتقل إلى العملاء في الشريط الجانبي للبوابة وانقر على عميل جديد. أدخل clientId وclientName لتطبيقك. ثم أضف في تبويب عناوين URI الخاص بالعميل عنوان إعادة توجيه واحدًا على الأقل، وهو المكان الذي يُرسَل إليه المستخدمون بعد المصادقة. على سبيل المثال: https://app.example.com/callback. يتطلب العملاء الجدد سرَّ عميل افتراضيًا، لذا لتطبيق متصفح بلا خادم خلفي أوقف طلب سر في تبويب عام.

New client form with Client ID and Client Name fields

سجّل عميل OAuth جديدًا في البوابة

التطوير المحلي

استخدم http://localhost:3000/callback كعنوان إعادة توجيه للتطوير المحلي. يسمح Authagonal بعناوين إعادة توجيه غير مشفّرة بـ HTTPS لمصادر localhost.

أول تسجيل دخول لك

أسرع طريقة للتكامل هي عبر oidc-client-ts، وهي مكتبة عميل OIDC خفيفة لتطبيقات JavaScript وTypeScript.

oidc-client-ts integration
import { UserManager } from 'oidc-client-ts';

const mgr = new UserManager({
  authority: 'https://acme.authagonal.io',
  client_id: 'my-app',
  redirect_uri: 'https://app.example.com/callback',
  response_type: 'code',
  scope: 'openid profile email',
});

// Redirect to login
mgr.signinRedirect();

// On callback page
const user = await mgr.signinRedirectCallback();
console.log(user.profile); // { sub, email, name, ... }

إذا كنت تفضّل نهجًا بسيطًا دون مكتبة، يمكنك استخدام تدفق رمز التفويض القياسي في OAuth 2.0 مع fetch البسيط:

Minimal fetch-based flow
// 1. Redirect the user to the authorization endpoint
const authorizeUrl = new URL('https://acme.authagonal.io/connect/authorize');
authorizeUrl.searchParams.set('client_id', 'my-app');
authorizeUrl.searchParams.set('redirect_uri', 'https://app.example.com/callback');
authorizeUrl.searchParams.set('response_type', 'code');
authorizeUrl.searchParams.set('scope', 'openid profile email');
authorizeUrl.searchParams.set('code_challenge', codeChallenge);
authorizeUrl.searchParams.set('code_challenge_method', 'S256');
window.location.href = authorizeUrl.toString();

// 2. On the callback page, exchange the code for tokens
const res = await fetch('https://acme.authagonal.io/connect/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: new URLSearchParams(window.location.search).get('code')!,
    redirect_uri: 'https://app.example.com/callback',
    client_id: 'my-app',
    code_verifier: codeVerifier,
  }),
});

const tokens = await res.json();
// tokens.id_token, tokens.access_token (refresh_token only when offline_access is requested and allowed)
Authagonal login page with email and password fields, branded with tenant logo

صفحة تسجيل الدخول الافتراضية لمستأجرك

وضع بيئة الاختبار

اختبر تكاملك في بيئة اختبار أولًا. أنشئ واحدة ضمن البيئات في البوابة: تحصل كل بيئة اختبار على عنوان URL خاص بها ({env}-{slug}.authagonal.io، مثل test1-acme.authagonal.io) ويمكن إعادة تعيينها إلى حالة فارغة في أي وقت دون التأثير على المستخدمين الفعليين.

لوحة التحكم

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

نظرة عامة

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

Full dashboard view showing the welcome banner, stat cards, monthly active users meter, and sign-in activity chart

الشاشة الرئيسية للوحة التحكم مع البطاقات الإحصائية ونشاط تسجيل الدخول

مقاييس النشاط

تلخّص ست بطاقات إحصائية حالة مستأجرك بنظرة سريعة:

  • المستخدمون النشطون: إجمالي عدد المستخدمين في مستأجرك
  • عمليات تسجيل الدخول (24 ساعة): عمليات تسجيل الدخول الناجحة خلال آخر 24 ساعة
  • المسجّلون في MFA: نسبة المستخدمين المسجّلين في MFA، مع عدد المسجّلين والعدد الإجمالي
  • المحاولات الفاشلة (24 ساعة): عمليات تسجيل الدخول الفاشلة خلال آخر 24 ساعة، مثل بيانات الاعتماد غير الصحيحة أو الحسابات المقفلة أو حالات الرفض بسبب السياسة
  • مزامنة SCIM: نشاط التزويد من موفّري الهوية المتصلين، ويُعرض بحالة «خامل» أو بعدد العمليات
  • الإنفاق الشهري: الإنفاق حتى الآن هذا الشهر، مع رقم متوقَّع لنهاية الشهر

تقارن بطاقات الـ 24 ساعة آخر 24 ساعة بالـ 24 ساعة التي سبقتها. ويرسم مخطط نشاط تسجيل الدخول عمليات تسجيل الدخول الناجحة والفاشلة يوميًا على مدى 14 أو 30 أو 90 يومًا. وتتحدّث لوحة التحكم كل دقيقة.

Six stat cards showing active users, sign-ins, MFA enrolment, failed attempts, SCIM sync, and monthly spend

بطاقات إحصائية تلخّص آخر 24 ساعة

التنقل السريع

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

العملاء

يمثّل عملاء OAuth التطبيقات التي تُصادق المستخدمين عبر مستأجرك. لكل عميل تهيئته الخاصة لعناوين إعادة التوجيه، والنطاقات، وأنواع المنح، ومدد صلاحية الرموز، وسياسة MFA.

قائمة العملاء

تعرض صفحة العملاء جدولًا بجميع العملاء المسجّلين. يُظهر كل صف clientId، والاسم المعروض، وأنواع المنح المسموح بها كشارات ملونة، وما إذا كان PKCE مفعّلًا. انقر على أي صف لفتح محرّر التهيئة الكامل.

Clients table showing clientId, name, grant type badges, and PKCE status for each registered application

قائمة العملاء مع شارات أنواع المنح ومؤشرات PKCE

إنشاء عميل

انقر على عميل جديد لتسجيل تطبيق جديد. تحتاج إلى تقديم حقلين:

  • clientId ، معرّف فريد للعميل (مثل my-spa)
  • clientName ، اسم معروض مقروء للبشر
New client form with Client ID and Client Name input fields

سجّل عميل OAuth جديدًا

حذف عميل

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

مرجع تهيئة العميل

لكل عميل مجموعة شاملة من خيارات التهيئة منظّمة في خمسة تبويبات: عام، وعناوين URI، والنطاقات والمنح، والرموز، والأمان.

الإعدادات العامة

الإعدادالوصفالافتراضي
clientNameالاسم المعروض في شاشات الموافقة وفي البوابة–
requirePkceاشتراط Proof Key for Code Exchange في تدفقات رمز التفويضمُفعّل
requireClientSecretاشتراط سر العميل لطلبات الرموز (عطّله للعملاء العامين مثل تطبيقات الصفحة الواحدة SPAs)مُفعّل
allowOfflineAccessالسماح للعميل بطلب رموز التحديث عبر نطاق offline_accessمُعطّل
alwaysIncludeUserClaimsInIdTokenتضمين مطالبات الملف الشخصي والبريد الإلكتروني والأدوار والمجموعات في رمز الهوية حتى عندما لا تُطلب النطاقات المطابقةمُعطّل
includeGroupsInTokensتضمين أسماء مجموعات SCIM الخاصة بالمستخدم كمطالبة groups، في الرموز الصادرة عند طلب النطاق groupsمُعطّل

أمان PKCE

يقلّل تعطيل PKCE من أمان تدفقات رمز التفويض. لا تعطّل هذا إلا للعملاء القدامى الذين لا يدعمون PKCE. يجب أن تترك جميع التطبيقات الحديثة PKCE مفعّلًا.

العناوين (URIs)

تستخدم حقول URI إدخالًا على هيئة وسوم، اكتب قيمة واضغط Enter أو فاصلة لإضافتها. انقر على علامة X في أي وسم لإزالته.

الإعدادالوصف
redirectUrisعناوين رد النداء المسموح بها بعد المصادقة. يجب أن تطابق تمامًا معامل redirect_uri في طلبات التفويض.
postLogoutRedirectUrisالعناوين المسموح بإعادة التوجيه إليها بعد تسجيل الخروج.
allowedCorsOriginsالمصادر المسموح لها بإجراء طلبات عبر الأصول إلى نقطتي نهاية الرموز وUserInfo.
URI configuration section showing tag inputs for redirect URIs, post-logout URIs, and CORS origins

حقول إدخال على هيئة وسوم لتهيئة العناوين (URIs)

النطاقات وأنواع المنح

الإعدادالخيارات
allowedScopesopenid profile email offline_access phone roles groups
allowedGrantTypesauthorization_code client_credentials refresh_token urn:ietf:params:oauth:grant-type:device_code urn:ietf:params:oauth:grant-type:token-exchange

مدد صلاحية الرموز

الإعدادالوصفالافتراضي
accessTokenLifetimeSecondsمدة صلاحية رموز الوصول1800 (30 دقيقة)
identityTokenLifetimeSecondsمدة صلاحية رموز الهوية300 (5 دقائق)
authorizationCodeLifetimeSecondsمدة صلاحية رموز التفويض للاستبدال300 (5 دقائق)
absoluteRefreshTokenLifetimeSecondsالحد الأقصى لمدة صلاحية رمز التحديث بغض النظر عن النشاط2592000 (30 يومًا)
slidingRefreshTokenLifetimeSecondsتُعاد ضبط مدة انتهاء رمز التحديث عند كل استخدام، حتى الحد الأقصى للمدة المطلقة1296000 (15 يومًا)
Token lifetime configuration fields with numeric inputs for each lifetime setting

اضبط مدد صلاحية الرموز لكل عميل

عناوين تسجيل الخروج

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

الإعدادالوصف
backChannelLogoutUriطلب POST من خادم إلى خادم مع رمز تسجيل خروج موقّع. موثوق حتى عندما يكون متصفّح المستخدم غير متصل.
frontChannelLogoutUriيُعرض في إطار iframe مخفي أثناء تسجيل الخروج حتى يمسح المتصفّح ملفات تعريف الارتباط والتخزين المحلي.
frontChannelLogoutSessionRequiredعند تفعيله، يتلقى عنوان تسجيل الخروج معاملي الاستعلام iss وsid حتى يتمكن تطبيقك من ربط تسجيل الخروج بالجلسة المحددة.

استخدمهما معًا

تضمن القناة الخلفية إبلاغ الخادم، بينما تمسح القناة الأمامية المتصفّح. تستفيد معظم التطبيقات من تهيئة كليهما.

سياسة MFA

لكل عميل سياسة MFA خاصة به، تُضبط في تبويب <strong>الأمان</strong> الخاص بالعميل. تقدّم قائمة سياسة MFA المنسدلة ثلاثة خيارات:

السياسةالسلوك
مُعطّلةلا يُطلب MFA أبدًا لهذا العميل
مُفعّلةيمكن للمستخدمين التسجيل اختياريًا في MFA، وسيُطلب منهم إذا كانوا مسجّلين
مطلوبةيجب على جميع المستخدمين إكمال MFA للمصادقة عبر هذا العميل
MFA policy dropdown showing Disabled, Enabled, and Required options on the client configuration page

سياسة MFA لكل عميل

SSO للمؤسسات

يتيح SSO للمؤسسات لعملائك استخدام موفّر الهوية الخاص بهم. يدعم Authagonal كلًا من اتحاد SAML 2.0 وOIDC مع التوجيه القائم على النطاق، بحيث يُوجَّه المستخدمون تلقائيًا إلى موفّر الهوية الصحيح بناءً على عنوان بريدهم الإلكتروني.

SSO domain routing flow: shows how email domains are matched to SAML or OIDC identity providers

التوجيه القائم على النطاق لـ SSO

اتصالات SAML 2.0

لإنشاء اتصال SAML، انتقل إلى صفحة SSO وحدّد علامة التبويب SAML. قدّم ما يلي:

الحقلالوصف
connectionNameاسم مقروء للبشر لهذا الاتصال (مثل "Acme Corp Okta")
entityIdمعرّف كيان SP الخاص بك. سجّل هذه القيمة نفسها لدى IdP كمعرّف التطبيق (Entity ID)؛ ويجب أن تذكرها التأكيدات بوصفها Audience
metadataLocationعنوان URL لمستند XML لبيانات تعريف SAML الخاص بـ IdP
metadataXmlXML لبيانات تعريف IdP ملصوق، من أجل IdP بلا عنوان URL لبيانات التعريف (Google Workspace) أو يتعذر الوصول إلى عنوانه من الإنترنت. قدّم هذا أو metadataLocation، وليس كليهما
nameIdFormatتنسيق NameID اختياري يُطلب من IdP. اتركه فارغًا للافتراضي emailAddress، أو اضبطه على "none" لإسقاط NameIDPolicy كليًا (موصى به مع ADFS)
allowedDomainsنطاقات البريد الإلكتروني الموجَّهة إلى هذا الاتصال (مثل acme.com). تُضبط عبر الـ API، وتعرضها البوابة على بطاقة الاتصال وفي تبويب توجيه النطاقات

عند حفظ الاتصال، يجلب Authagonal وثيقة البيانات الوصفية ويستورد شهادة التوقيع الخاصة بموفّر الهوية، وعنوان URL لنقطة نهاية SSO، وصيغة معرّف الاسم. تُحدّث البيانات الوصفية دوريًا لالتقاط عمليات تدوير الشهادات.

SAML connection creation form with fields for connection name, SP entity ID, and IdP metadata

إنشاء اتصال SSO بـ SAML 2.0

اتصالات OIDC

لإنشاء اتصال اتحاد OIDC، حدّد علامة التبويب OIDC وقدّم:

الحقلالوصف
connectionNameاسم مقروء للبشر لهذا الاتصال
metadataLocationعنوان اكتشاف OpenID Connect (مثل https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration)
clientIdمعرّف العميل المسجّل لدى موفّر الهوية الخارجي لهذا الاتحاد
clientSecretسر العميل لتسجيل موفّر الهوية الخارجي
allowedDomainsنطاقات البريد الإلكتروني الموجَّهة إلى هذا الاتصال (مثل acme.com). تُضبط عبر الـ API، وتعرضها البوابة على بطاقة الاتصال وفي تبويب توجيه النطاقات
OIDC connection creation form with fields for connection name, discovery URL, client ID, and client secret

إنشاء اتصال اتحاد OIDC

التوجيه القائم على النطاق

يعيد التوجيه القائم على النطاق توجيه المستخدمين تلقائيًا إلى موفّر الهوية الصحيح بناءً على نطاق بريدهم الإلكتروني. عندما يُدخل مستخدم بريده الإلكتروني في صفحة تسجيل الدخول، يتحقق Authagonal مما إذا كان جزء النطاق (مثل acme.com) يطابق allowedDomains لأي اتصال SSO. وإذا تطابق، يُعاد توجيه المستخدم بسلاسة إلى موفّر الهوية الخاص بمؤسسته.

نطاق البريد الإلكترونيموفّر SSOالبروتوكول
acme.comAcme Corp OktaSAML 2.0
contoso.comContoso Azure ADOIDC
example.orgExample OneLoginSAML 2.0
Domain routing table showing email domains mapped to SSO connections with protocol type

يربط التوجيه القائم على النطاق نطاقات البريد الإلكتروني بموفّري الهوية

التدفق الذي يبدأه موفّر الخدمة (SP)

التدفق الذي يبدأه موفّر الخدمة هو الافتراضي، إذ يبدأ المستخدمون من صفحة تسجيل الدخول الخاصة بك ويُوجَّهون تلقائيًا إلى موفّر الهوية الصحيح. يمكن أيضًا ربط المستخدمين مباشرةً باتصال محدد عبر /saml/{connectionId}/login أو /oidc/{connectionId}/login.

تزويد JIT

عندما يسجّل مستخدم الدخول عبر SSO لأول مرة ولم يكن موجودًا بالفعل في مستأجرك، يمكن لـ Authagonal إنشاء حسابه تلقائيًا (التزويد الفوري Just-In-Time). التزويد الفوري JIT معطّل افتراضيًا: فعّله لكل اتصال عبر تحديد تفعيل الإنشاء التلقائي عند أول دخول عند إنشاء الاتصال.

عند تعطيل تزويد JIT، لا يمكن تسجيل الدخول عبر ذلك الاتصال إلا للمستخدمين الذين تم تزويدهم مسبقًا، سواء عبر SCIM أو صفحة المستخدمين في البوابة أو الـ API. يتلقى المستخدمون غير المعروفين خطأ access_denied ويُوجَّهون للتواصل مع المسؤول الخاص بهم.

إعداد لكل اتصال

يُتحكَّم في تزويد JIT لكل اتصال SSO، وليس على مستوى المستأجر بالكامل. يمكنك أن يكون لديك اتصال يسمح بـ JIT (مثلًا لمؤسسة شريكة تدير مستخدميها بنفسها) وآخر يتطلب التزويد المسبق (مثلًا لعميل مؤسسي يستخدم مزامنة SCIM).

اختبر قبل الطرح

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

اتصالات مقيّدة بمنظمة

يمكن أيضًا أن يتبع الاتصال منظمة واحدة داخل مستأجرك بدلًا من المستأجر بأكمله. ولا يُعرض إلا بعد تحديد تلك المنظمة مسبقًا: عبر نطاق مخصص مثبّت عليها، أو معامل organization في رابط تسجيل الدخول، أو عميل مسجّل لتلك المنظمة وحدها. ولا يُعرض أبدًا في صفحة تسجيل دخول على مستوى المستأجر. ويُفحص أيٌّ من هذه المصادر يتقدم وفق هذا الترتيب، من الأعلى أولوية إلى الأدنى.

تسجيل الدخول ينشئ العضوية

المستخدم الذي يسجّل الدخول عبر اتصال مقيّد بمنظمة يصبح تلقائيًا عضوًا في تلك المنظمة، بالطريقة نفسها التي ينشئ بها التزويد الفوري (JIT) حسابه، فلا توجد خطوة دعوة منفصلة.

تفرّد النطاق يُحتسب لكل نطاق عمل

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

المستخدمون

تتيح لك صفحة المستخدمين إدارة جميع المستخدمين النهائيين في مستأجرك. يمكنك البحث عن المستخدمين، وعرض تفاصيلهم، ودعوة مستخدمين جدد، ومعرفة كيفية تزويد كل مستخدم.

يطابق شريط البحث معرّف مستخدم أو بريدًا إلكترونيًا مطابقًا تمامًا، أو بادئة البريد الإلكتروني أو الاسم الأول أو اسم العائلة، وتضيّق عوامل التصفية «الكل» و«نشط» و«غير نشط» القائمة حسب الحالة. يجري البحث بتأخير قدره 300 مللي ثانية بحيث تتحدّث النتائج أثناء الكتابة دون إثقال الـ API. تُرقَّم النتائج بمعدل 50 مستخدمًا لكل صفحة، استخدم عناصر التحكم في التنقل أسفل الجدول للانتقال بين الصفحات.

جدول المستخدمين

يعرض جدول المستخدمين الأعمدة التالية لكل مستخدم:

العمودالوصف
المستخدماسم المستخدم (أو بريده الإلكتروني عند عدم تعيين اسم)، مع بريده الإلكتروني أسفله وشارة «غير مُتحقَّق منه» إلى أن يُؤكَّد البريد الإلكتروني
الحالةActive أو Inactive ، يشير إلى ما إذا كان الحساب مُفعّلًا
المصدرSCIM أو Local ، كيفية إنشاء المستخدم
الأدوارالأدوار المعيّنة للمستخدم
MFAEnabled عند تسجيل المصادقة متعددة العوامل، وإلا تظهر شرطة
تاريخ الإنشاءتاريخ إنشاء حساب المستخدم
User list table with columns for user, status, source, roles, MFA, and created date

قائمة المستخدمين مع شريط البحث والترقيم

دعوة المستخدمين

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

الحقلالوصف
emailعنوان البريد الإلكتروني للمستخدم (يجب أن يكون فريدًا داخل المستأجر)
firstNameالاسم الأول للمستخدم
lastNameاسم عائلة المستخدم
localeاللغة المفضّلة. تحدّد لغة واجهة المستخدم والبريد الإلكتروني للمستخدم، وهي اختيارية وتعود افتراضيًا إلى الإنجليزية.
organizationIdمنظمة اختيارية لإضافة المستخدم إليها، مع أدواره فيها. تظهر عندما تكون لدى مستأجرك منظمات
Invite user form with email, first name, last name, and Language fields

دعوة مستخدم جديد

المستخدمون المُزوَّدون عبر SCIM

يُوسَم المستخدمون المُنشَؤون عبر SCIM بشارة "SCIM" في عمود المصدر. وتُدار دورة حياتهم (الإنشاء والتحديثات والتعطيل) بواسطة موفّر الهوية الأساسي.

اللغة المفضّلة

لكل مستخدم لغة مفضّلة تتحكم في كل من واجهته المستضافة ورسائل البريد الإلكتروني الخاصة بالمعاملات التي يرسلها له Authagonal (التحقق، وإعادة ضبط كلمة المرور، والترحيب، وغير ذلك). يمكنك تعيينها عند دعوة المستخدم وتغييرها في أي وقت من صفحة تفاصيل المستخدم. إذا لم تكن لدى المستخدم لغة مفضّلة محددة، يعود Authagonal افتراضيًا إلى الإنجليزية. يقدّم المُحدِّد جميع اللغات المدعومة: الإنجليزية، والصينية (المبسّطة)، والألمانية، والفرنسية، والإسبانية، والفيتنامية، والبرتغالية، واليابانية، والعربية، والهندية، والأفريكانية.

User detail edit form with profile fields including a preferred Language selector

عيّن اللغة المفضّلة للمستخدم في صفحة التفاصيل

تفاصيل المستخدم

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

User detail page showing profile fields, status, assigned roles, and custom attributes

الملف الشخصي

حرّر البريد الإلكتروني، والاسم الأول/الأخير، والهاتف، والشركة، واللغة، والمعرّف الخارجي، وبدّل علامة نشاط المستخدم. يتطلب تغيير البريد الإلكتروني أو علامة تأكيد البريد الإلكتروني مسؤولًا أو مالكًا. يجب أن تبقى تغييرات البريد الإلكتروني فريدة عبر المستأجر، ويُرجع الـ API email_already_in_use إذا كان مستخدمًا.

الأدوار

عيّن الأدوار المعرّفة في صفحة الأدوار وألغِ تعيينها. تُصدَر الأدوار المعيّنة بوصفها المطالبة roles في رموز الهوية والوصول عندما يطلب العميل النطاق roles.

المصادقة متعددة العوامل

اطّلع على كل بيانات اعتماد MFA المسجّلة للمستخدم (تطبيق المصادقة (TOTP)، وWebAuthn/مفاتيح المرور، ورموز الاسترداد)، لكل منها طوابعها الزمنية الخاصة بالتسجيل وآخر استخدام. أزِل بيانات اعتماد فردية، أو أعد ضبط جميع عوامل MFA، ويتطلب كلا الإجراءين مسؤولًا أو مالكًا. تجبر إعادة الضبط المستخدم على إعادة التسجيل عند تسجيل الدخول التالي.

السمات المخصصة

بيانات مفتاح/قيمة اعتباطية مرتبطة بالمستخدم. يجب أن تكون المفاتيح فريدة. تُكشف السمات عبر API الملف الشخصي للمستخدم وعبر SCIM، ويمكن ربطها بمطالبات رمز الوصول عبر تهيئة userClaims لنطاق مخصص.

المؤسسة

المؤسسة التي ينتمي إليها هذا المستخدم. وهي معرّف نصّي حر من عندك، يُصدَر بوصفه مطالبة org_id في رموزه وعلى /connect/userinfo ضمن نطاق profile. لا يشتقّه Authagonal أبدًا: بل يضبطه تطبيق التزويد لديك، أو بيانات اعتماد SCIM التي أنشأت المستخدم، أو يُضبط يدويًا من هنا.

يعرض الرابط المجاور للحقل كل من يشترك في القيمة نفسها، والمرشِّح نفسه متاح على الـ API بصيغة GET /api/v1/users?organizationId=. استخدمه لمعرفة من ينتمي إلى زبون معيّن دون تصفّح الدليل بأكمله.

حذف المستخدم

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

المجموعات

تتيح لك المجموعات تنظيم المستخدمين وتضمين عضوية المجموعة في الرموز. يمكن إنشاء المجموعات يدويًا في البوابة أو تزويدها تلقائيًا عبر SCIM من مزوّد هوية خارجي.

قائمة المجموعات

تُسرَد المجموعات في تبويب المجموعات بصفحة SCIM، مع المعلومات التالية:

العمودالوصف
اسم المجموعةالاسم المعروض للمجموعة
الأعضاءعدد المستخدمين الموجودين حاليًا في المجموعة
المصدرSCIM أو Manual كيفية إنشاء المجموعة
تاريخ الإنشاءتاريخ إنشاء المجموعة
Groups list table showing group name, member count, source badge, granted roles, and created date

قائمة المجموعات مع مؤشرات المصدر

إنشاء مجموعة

انقر فوق مجموعة جديدة وأدخِل الاسم المعروض للمجموعة. ينبغي أن تكون أسماء المجموعات وصفية وفريدة داخل المستأجر الخاص بك (مثل "Engineering" و"Billing Admins" و"Beta Testers").

تفاصيل المجموعة والأعضاء

انقر فوق أي مجموعة لفتح عرض التفاصيل. هنا يمكنك رؤية جميع الأعضاء الحاليين وإدارة العضوية:

  • إضافة أعضاء: ابحث عن مستخدم بالبريد الإلكتروني أو الاسم وأضِفه إلى المجموعة.
  • إزالة الأعضاء: انقر فوق زر الإزالة بجوار أي عضو وأكّد. تُلغى أي أدوار مُنحت عبر المجموعة.
Group detail view showing the member list, a user search to add members, and the roles the group grants

إدارة عضوية المجموعة في عرض التفاصيل

المجموعات في الرموز

عند تفعيل المجموعات في الرموز على عميل وطلب النطاق groups، تتضمن الرموز الصادرة مطالبة groups تسرد الأسماء المعروضة لمجموعات المستخدم:

groups claim
{
  "sub": "user-123",
  "email": "[email protected]",
  "groups": ["Engineering", "Beta Testers"]
}

التفعيل لكل عميل

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

الأدوار

تدعم الأدوار التحكم في الوصول المستند إلى الأدوار (RBAC) في تطبيقك. عرّف الأدوار في Authagonal، وخصّصها للمستخدمين، واستخدم مطالبة roles في الرموز لفرض التفويض في منطق تطبيقك.

إدارة الأدوار

تعرض صفحة الأدوار جدولًا بجميع الأدوار المعرّفة مع التحرير المباشر. لكل دور:

العمودالوصف
الاسممعرّف فريد للدور (مثل "admin" و"editor" و"viewer")
الوصفوصف مقروء يوضّح ما يمنحه الدور
تاريخ الإنشاءتاريخ إنشاء الدور

إنشاء دور

انقر فوق دور جديد وقدّم اسمًا ووصفًا. ينبغي أن تكون أسماء الأدوار موجزة وأن تتبع اصطلاح تسمية متسقًا عبر تطبيقك (مثل الأحرف الصغيرة مع الشرطات: billing-admin).

التحرير المباشر

تدعم الأدوار التحرير المباشر مباشرةً في الجدول. انقر فوق أيقونة القلم على أي دور للدخول إلى وضع التحرير، فتصبح حقول الاسم والوصف قابلة للتحرير. عدّل القيم، ثم انقر فوق أيقونة علامة الصح للحفظ. تسري التغييرات على الفور.

حذف دور

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

Roles table with inline editing active, showing editable name and description fields with save and cancel icons

التحرير المباشر للأدوار في جدول الأدوار

الأدوار في الرموز

تُضمَّن الأدوار المخصصة لمستخدم كمطالبة roles في رموز الهوية والوصول عندما يطلب العميل النطاق roles. يمكن لتطبيقك قراءة هذه المطالبة لاتخاذ قرارات التفويض:

roles claim in ID token
{
  "sub": "user-123",
  "email": "[email protected]",
  "roles": ["admin", "billing-admin"]
}

تزويد SCIM

يتيح SCIM 2.0 (نظام إدارة الهوية عبر النطاقات) التزويد التلقائي للمستخدمين والمجموعات من مزوّدي الهوية المؤسسية مثل Okta وAzure AD وOneLogin وJumpCloud. عند ضبطه، تُزامَن حسابات المستخدمين وعضويات المجموعات تلقائيًا من مزوّد الهوية الأعلى إلى المستأجر الخاص بك في Authagonal.

SCIM provisioning flow: shows user lifecycle events flowing from enterprise IdP through Authagonal SCIM API to your app via TCC webhooks

مزامنة دورة حياة مستخدم SCIM مع التزويد إلى الأنظمة التابعة

خطوات الإعداد

اتبع هذه الخطوات لتفعيل تزويد SCIM لعميل:

  1. اختر تطبيق العميل: اختر عميل OAuth الذي سيرتبط به تزويد SCIM.
  2. أنشئ رمز SCIM: قدّم وصفًا ومدة صلاحية بالأيام، ثم أنشئ الرمز.
  3. انسخ الرمز فورًا: تُعرض قيمة الرمز الخام مرة واحدة فقط. انسخها قبل إغلاق مربع الحوار.
  4. اضبط مزوّد الهوية لديك: في إعدادات SCIM لمزوّد الهوية، أدخِل عنوان URL الأساسي ورمز الحامل.
  5. اختبر مزامنة المستخدمين: شغّل مزامنة اختبارية من مزوّد الهوية وتحقق من ظهور المستخدمين في بوابة Authagonal.

عنوان URL الأساسي لـ SCIM

اضبط مزوّد الهوية لديك بعنوان URL الأساسي التالي:

SCIM Base URL
https://{slug}.authagonal.io/scim/v2

استبدل {slug} بسلَج المستأجر الخاص بك.

SCIM configuration page showing client selector, token generation form, and base URL

صفحة إعداد SCIM مع إنشاء الرموز

إدارة الرموز

تصادق رموز SCIM على طلبات التزويد الواردة من مزوّد الهوية لديك. يمكنك إدارة عدة رموز لكل عميل:

الحقلالوصف
الوصفتسمية لتحديد الرمز (مثل "Okta Production SCIM")
انتهاء الصلاحيةعمر الرمز بالأيام (من 1 إلى 3650، والقيمة الافتراضية 365).
الحالةالرموز النشطة قيد الاستخدام. تعرض الرموز المُبطَلة شارة Revoked ولم يعد بإمكانها المصادقة على الطلبات.

لإبطال رمز، انقر فوق زر إبطال المجاور له. تبقى الرموز المُبطَلة مرئية في القائمة لأغراض التدقيق لكنها تتوقف فورًا عن قبول الطلبات.

SCIM token list showing active and revoked tokens with description, expiry date, and revoke button

إدارة الرموز مع مؤشرات الرموز النشطة والمُبطَلة

انسخ الرمز فورًا

يُعرض رمز SCIM الخام مرة واحدة فقط عند إنشائه. انسخه فورًا، فلا يمكن استرجاعه لاحقًا. إذا فقدت الرمز، فستحتاج إلى إنشاء رمز جديد وتحديث إعدادات مزوّد الهوية لديك.

اختبار الاتصال

تحقق من أن تكامل SCIM لديك يعمل عبر الاستعلام عن نقطة نهاية ServiceProviderConfig:

Test SCIM connectivity
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://acme.authagonal.io/scim/v2/ServiceProviderConfig

تُعيد الاستجابة الناجحة مستند JSON يصف ميزات SCIM المدعومة: PATCH والتصفية مدعومان، بينما العمليات المجمّعة وتغيير كلمة المرور والفرز وETags غير مدعومة.

اللغة المفضّلة

تُربَط سمة SCIM المسماة preferredLanguage (مع الرجوع إلى locale) بلغة المستخدم المخزّنة. يتلقى مستخدمو SSO المزوّدون عبر SCIM رسائل بريد إلكتروني مترجمة تلقائيًا باللغة التي يرسلها مزوّد الهوية لديهم.

ما الذي تراه بيانات الاعتماد

لا ترى بيانات اعتماد SCIM إلا المستخدمين والمجموعات التي زوّدتها هي. فقراءة مستخدم أنشأه موصِّل آخر أو تحديثه أو حذفه تُجيب بـ 404، ولا يُعيد السرد إلا ما يخصّها، ولا يجوز أن تسمّي عضوية المجموعة سوى مستخدمين زوّدهم الموصِّل نفسه. أما الحسابات المُنشأة بأي طريقة أخرى، سواء بواسطة مسؤول أو عبر تسجيل ذاتي أو عبر التزويد الفوري من SSO، فهي غير مرئية لـ SCIM إطلاقًا.

هذا الحد يسري لكل عميل، لا لكل رمز. فبيانات اعتماد اثنتان صادرتان على العميل نفسه هما هوية واحدة بسرّين، وكلٌّ منهما تستطيع تعديل ما أنشأته الأخرى. امنح الموصِّلات غير الموثوقة فيما بينها عميلًا لكل منها. ويُحدَّد نطاق externalId بالطريقة نفسها، فيمكن لموصِّلَين أن يستخدم كلٌّ منهما ext-001 لشخصين مختلفين دون تعارض.

إلغاء التزويد

DELETE /scim/v2/Users/{id} يعطّل الحساب ويضع عليه علامة محذوف. يُحتفظ بالسجل، كما يسمح RFC 7644، لكنه يُجيب بـ 404 على كل عملية لاحقة ويُستبعد من القوائم. تُمسح تسجيلات MFA وعضويات المجموعات الخاصة به، ويُحرَّر ربط externalId، وتُبطَل جميع الرموز الصادرة، فينتهي الوصول فورًا بدلًا من انتهائه عند انقضاء صلاحية الرمز التالي.

إذا أُعيد توظيف الشخص نفسه لاحقًا وأُعيد إنشاؤه، فسيحصل على معرّف مستخدم جديد. لا يُعاد استخدام المعرّفات أبدًا: فالمعرّف هو الـ subject في كل رمز أصدرته حتى الآن، لذا فإن إعادة استخدامه ستمنح الموظف الجديد بصمت سجلَّ صاحبه السابق في كل تطبيق يثق بهذا المعرّف.

وسم المستخدمين المزامَنين بمؤسسة

لا يوفّر SCIM أي وسيلة تتيح للموصِّل أن يذكر أيَّ زبائنك يزامن. لا يعرّف SCIM الأساسي أي سمة للمؤسسة، لذا فإن إنشاء مستخدم عادي يخبرك باسم الشخص وبريده الإلكتروني ولا شيء عمّن ينتمي إليه. وإذا زوّد عدة زبائن مستخدمين داخل مستأجرك، فسيصل مستخدموهم غير قابلين للتمييز بعضهم عن بعض.

تجيب عنه بيانات الاعتماد بدلًا من الطلب. عند إنشاء رمز SCIM، اختر إحدى منظمات مستأجرك ضمن المؤسسة (يظهر المنتقي بمجرد أن تكون لدى مستأجرك منظمات). يصبح كل مستخدم يُزوَّد عبر ذلك الرمز عضوًا نشطًا في تلك المنظمة، ويحملها بوصفها مطالبة org_id في رموزه من ذلك الحين. أصدِر بيانات اعتماد واحدة لكل زبون على العميل نفسه، فيخرج مستخدموهم المزامَنون منسوبين على نحو صحيح دون تسجيل عميل مستقل لكل واحد. اتركه فارغًا فيبقى المستخدمون بلا وسم.

الوسم ليس عزلًا

تُفرَض الملكية لكل عميل، لا لكل رمز. فبيانات اعتماد اثنتان على العميل نفسه هما هوية واحدة بسرّين: كلٌّ منهما تستطيع قراءة المستخدمين الذين أنشأتهم الأخرى وإعادة تسميتهم وتعطيلهم وحذفهم. لا بأس بذلك ما دمتَ تحتفظ بجميع بيانات الاعتماد بنفسك. أما إذا كان فريق تقنية المعلومات لدى كل زبون يحتفظ ببياناته، فامنح كل واحد منهم عميلًا خاصًا به، واضبط المؤسسة على بيانات اعتماده أيضًا.

يُطبَّق الوسم عند إنشاء المستخدم ولا يُطبَّق أبدًا عند تحديث لاحق، لذا لا تستطيع مزامنة تزايدية روتينية أن تنقل حسابًا قائمًا بصمت. وإذا كنت تشغّل كذلك تطبيق تزويد، فإن الوسم الصريح في بيانات الاعتماد هو الذي يفوز: لا تملأ استجابة /try إلا مؤسسة ما تزال فارغة.

المخططات المدعومة

ننفّذ مخططَي SCIM 2.0 الأساسيين User وGroup (RFC 7643). سمات المستخدم المدعومة هي userName وname.givenName وname.familyName وdisplayName وemails وactive وexternalId وpreferredLanguage / locale.

امتداد المستخدم المؤسسي غير مُنفَّذ، لذا تُقبل السمات department وmanager وemployeeNumber وcostCenter وdivision وorganization ثم تُتجاهَل بدلًا من تخزينها، وذلك في الإنشاء والاستبدال وPATCH على حد سواء. يربط كل من Entra وOkta بعضها افتراضيًا، فلا حاجة إلى إزالتها من خريطة السمات لديك. ولنسب مستخدم إلى أحد زبائنك، اضبط المؤسسة على بيانات اعتماد SCIM بدلًا من ذلك: فسمة organization المؤسسية يؤكّدها مزوّد الهوية لدى زبونك، وهي عمدًا لا تصبح org_id الخاص به.

نطاقات OAuth

تتيح النطاقات للعملاء طلب شرائح محددة من بيانات المستخدم أو أذوناته. يدعم Authagonal نطاقات OIDC القياسية والنطاقات المخصصة التي تعرّفها لواجهات API الخاصة بك.

النطاقات المدمجة

النطاقالوصف
openidمطلوب لأي تدفق OpenID Connect. يُصدر رمز هوية.
profileيعيد مطالبات الملف الشخصي القياسية (name وgiven_name وfamily_name وlocale وorg_name).
emailيعيد عنوان البريد الإلكتروني للمستخدم وحالة التحقق منه.
phoneيعيد رقم هاتف المستخدم (phone_number).
offline_accessيُصدر رمز تحديث إلى جانب رمز الوصول.
rolesيُصدر مطالبة roles الخاصة بالمستخدم. وبدون هذا النطاق، لا تُصدَر الأدوار.
groupsيُصدر مطالبة groups الخاصة بالمستخدم (عضوية مجموعات SCIM). وبدون هذا النطاق، لا تُصدَر المجموعات.

النطاقات المخصصة

عرّف نطاقاتك الخاصة في صفحة النطاقات. يصف كل نطاق إذناً أو مورداً يمكن للعميل طلبه (على سبيل المثال، billing.read وorders.write).

Custom scope creation form with name, display name, description and User Claims fields
الحقلالوصف
nameمعرّف النطاق المُرسَل في طلبات الرموز (مثل billing.read).
displayNameتسمية مقروءة تظهر على شاشة الموافقة.
descriptionشرح أطول يظهر أسفل اسم العرض عند الموافقة.
userClaimsمطالبات إضافية تُضاف إلى رمز الوصول ورمز الهوية عند منح هذا النطاق.
showInDiscoveryDocumentإذا كان مفعّلاً، يظهر النطاق في /.well-known/openid-configuration.
emphasizeيُبرز النطاق على شاشة الموافقة باعتباره حسّاساً.
requiredيمنع المستخدم من إلغاء تحديد النطاق أثناء الموافقة.
groupمجموعة الموافقة: تظهر النطاقات التي تتشارك عنوانًا معًا على شاشة الموافقة تحت مربع اختيار واحد. للعرض فقط.
allowedRolesالأدوار التي يجب أن يحملها المستخدم ليُمنح هذا النطاق. القيمة الفارغة تسمح للجميع، والمستخدم الذي لا يحمل أحد هذه الأدوار يُسقَط النطاق من رمزه بدلًا من رفضه.

تكامل الموافقة

يطلب العملاء الذين لديهم RequireConsent: true الموافقة من المستخدم عند أول طلب. وحذف نطاق لا يبطل الرموز الصادرة بالفعل، فأبطلها صراحةً إذا لزم الأمر.

مطالبات مخصصة على الرموز

للمطالبات المخصصة شقّان. المصدر هو بيانات خاصة بكل مستخدم: لكل AuthUser قاموس customAttributes يمكنك تعبئته من البوابة (المستخدمون ← المستخدم ← السمات المخصصة) أو عبر SCIM أو عبر خطاف تزويد TCC. أما الإطلاق فهو خاص بكل نطاق: تسمّي قائمة userClaims لكل نطاق المفاتيح التي تسمح بمغادرتها للخادم.

عندما يطلب عميل نطاقات، يمرّ Authagonal على النطاقات الممنوحة، ويوحّد قوائم userClaims الخاصة بها، ولا يُصدر إلا تلك المفاتيح من customAttributes الخاصة بالمستخدم. وتُسقَط المفاتيح غير المعروفة بصمت، فلا يستطيع عميل قراءة سمة بتخمين اسمها. أما مطالبات OIDC القياسية (sub وemail وname وغيرها) فتتبع المواصفة ولا تخضع للقائمة البيضاء.

Example: project-scope claims on an access token
# 1. On the user (Portal → Users → {user} → Custom Attributes)
department = "engineering"
employee_id = "E-1042"
seat_tier = "enterprise"

# 2. On a custom scope (Portal → Scopes → projects.read)
name        = "projects.read"
userClaims  = ["department", "seat_tier"]   # <-- whitelist

# 3. Client requests scope=openid projects.read
# Decoded access token (relevant fields only):
{
  "sub": "u-9b…",
  "scope": "openid projects.read",
  "department": "engineering",
  "seat_tier":  "enterprise"
  // employee_id is NOT emitted; it's not in the whitelist for any granted scope.
}

مطالبات الفيدرالية تملأ الفجوات لكل جلسة

عندما يسجّل مستخدم دخوله عبر موفّر هوية أصلي (SAML/OIDC SSO)، فإن المطالبات الخاصة بالجلسة الواردة من موفّر الهوية، مثل سمة department المُطابَقة من تأكيد SAML، تمرّ عبر القائمة البيضاء للنطاقات نفسها لكنها تملأ الفجوات فقط: عند تعارض المفاتيح تغلب قيمة customAttributes المُخزّنة. وتُصدر على رموز هذه الجلسة (وتبقى عبر دورات التحديث) دون أن تُكتب مرة أخرى في سجل المستخدم.

إسناد النطاقات إلى العملاء

أضف النطاقات المسموح بها في تبويب العملاء ← النطاقات & المنح. لا يمكن للعميل طلب سوى النطاقات الممنوحة له؛ وتُرفض النطاقات غير المعروفة بـ invalid_scope.

العلامة التجارية

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

المظهر

الإعدادالوصف
appNameاسم التطبيق المعروض في ترويسة صفحة تسجيل الدخول (عند عدم تعيين شعار) وفي رسائل البريد الإلكتروني الخاصة بالمعاملات
logoUrlعنوان URL لصورة شعارك. يُعرض في أعلى صفحة تسجيل الدخول. الحجم الموصى به: 200×60 بكسل أو نسبة أبعاد مماثلة.
primaryColorلون العلامة التجارية الأساسي المستخدم للأزرار والروابط وحالات التركيز. يُضبط عبر منتقي الألوان أو إدخال قيمة سداسية عشرية. تُحدَّث المعاينة المباشرة أثناء تغييرك للقيمة.
customCssUrlعنوان URL لملف CSS يُحمَّل بعد الأنماط الافتراضية. يجب أن يُقدَّم من الأصل نفسه لصفحة تسجيل الدخول، ويُتجاهَل أي عنوان URL على أصل آخر.
Branding appearance settings with app name input, logo URL field, color picker with hex input, and custom CSS URL field

إعدادات المظهر مع معاينة مباشرة للألوان

معلومات الاتصال

الإعدادالوصف
supportEmailعنوان بريد إلكتروني للدعم يُعرض على صفحات تسجيل الدخول. يراه المستخدمون عندما يحتاجون إلى مساعدة بشأن حساباتهم.

مفاتيح تبديل صفحة تسجيل الدخول

تحكّم في العناصر التي تظهر على صفحة تسجيل الدخول الخاصة بالمستأجر:

التبديلالوصفالافتراضي
showForgotPasswordإظهار رابط "نسيت كلمة المرور؟" في نموذج تسجيل الدخولمُفعّل
showRegistrationإظهار رابط "إنشاء حساب" لتسجيل المستخدمين بالخدمة الذاتيةمُفعّل
poweredByإظهار شارة "Powered by Authagonal" في أسفل صفحة تسجيل الدخولمُفعّل
A customized login page showing a branded logo, custom primary color on the sign-in button, and support email in the footer

مثال على صفحة تسجيل دخول مع تطبيق علامة تجارية مخصصة

CSS مخصص

للتحكم الكامل في مظهر صفحة تسجيل الدخول، قدّم عنوان URL لملف CSS في إعدادات علامتك التجارية. يُحمَّل الملف بعد الأنماط الافتراضية، لذا تكون الأولوية لقواعدك. يجب أن يكون عنوان URL على الأصل نفسه لصفحة تسجيل الدخول، ولا تُحمَّل أوراق الأنماط من الأصول الأخرى.

خصائص CSS المخصصة

تدعم صفحة تسجيل الدخول خصائص CSS المخصصة (المتغيرات) للتجاوزات الشائعة. اضبطها في ملف CSS الخاص بك لتغيير الألوان والخطوط والشكل دون كتابة محدِّدات معقدة.
/* your-custom-styles.css */
:root {
--auth-bg: #1a1a2e;
--auth-card-bg: #16213e;
--auth-heading: #e0e0e0;
--auth-radius: 12px;
--auth-font: 'Inter', sans-serif;
}
المتغيرالوصفالافتراضي
--auth-bgلون خلفية الصفحة#f3f4f6
--auth-card-bgخلفية بطاقة تسجيل الدخولwhite
--auth-headingلون نص العنوان#111827
--auth-radiusنصف قطر حدود البطاقة0.5rem
--auth-fontعائلة الخطinherit

الوضع الداكن

يأتي تطبيق تسجيل الدخول بسمات فاتحة وداكنة وتابعة للنظام. يختار إعداد الوضع الداكن في صفحة العلامة التجارية القيمة الافتراضية: إيقاف، أو تلقائي (يتبع تفضيل النظام، وهو الافتراضي)، أو فرض. ولا يزال بإمكان المستخدمين الاختيار من مفتاح تبديل على صفحة تسجيل الدخول، ويستمر الاختيار عبر الجلسات. عند الضبط على system، يتتبع التطبيق أحادي الصفحة قيمة prefers-color-scheme بشكل مباشر.

تُعلَن القيم الفاتحة عند :root، وتُحصر التجاوزات الداكنة ضمن .dark. تكون الأولوية دائمًا للعلامة التجارية للمستأجر المضبوطة عبر customCssUrl، لذا تستمر ألوانك بغض النظر عن سمة المستخدم.

محدِّدات العناصر

للتحكم الأدق، استهدف عناصر محددة باستخدام سمات data-auth. هذه المحدِّدات مستقرة عبر التحديثات، فلن تتعطل عند تغييرنا لأسماء الفئات الداخلية.
المحدِّدالعنصر
[data-auth="page"]حاوية خلفية الصفحة الكاملة
[data-auth="header"]منطقة الشعار واسم التطبيق
[data-auth="logo"]صورة الشعار
[data-auth="app-name"]عنوان اسم التطبيق (عند عدم ضبط شعار)
[data-auth="content"]منطقة المحتوى الرئيسية (النماذج والرسائل)
[data-auth="login-form"]عنصر نموذج تسجيل الدخول
[data-auth="email-field"]غلاف حقل إدخال البريد الإلكتروني
[data-auth="password-field"]غلاف حقل إدخال كلمة المرور
[data-auth="submit-button"]زر تسجيل الدخول
[data-auth="languages"]شريط منتقي اللغة

الإعدادات

اضبط سياسات الأمان على مستوى المستأجر وخطافات الويب وإعدادات البيئة. تنطبق هذه الإعدادات عالميًا عبر جميع العملاء ما لم تُتجاوز على مستوى العميل.

سياسة كلمات المرور

حدّد متطلبات تعقيد كلمات المرور لجميع المستخدمين في المستأجر الخاص بك، ضمن المستخدمون ← الإعدادات:

الإعدادالنطاقالافتراضي
minPasswordLength6 – 1288
requireUppercaseمُفعّل / معطّلمُفعّل
requireLowercaseمُفعّل / معطّلمُفعّل
requireDigitمُفعّل / معطّلمُفعّل
requireSpecialCharمُفعّل / معطّلمُفعّل
Password policy settings showing minimum length slider and toggle switches for character requirements

ضبط سياسة كلمات المرور

سياسة MFA

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

السياسةالسلوك
DisabledMFA غير متاحة. لا يمكن للمستخدمين التسجيل في MFA.
EnabledMFA اختيارية. يمكن للمستخدمين اختيار التسجيل وسيُطلَب منهم إدخالها عند تسجيل الدخول إذا كانوا مسجَّلين.
RequiredMFA إلزامية. يجب على جميع المستخدمين التسجيل في MFA وإكمال العامل الثاني في كل تسجيل دخول.

الجلسة والإقفال

تحكّم في مدة الجلسة وسلوك إقفال الحساب:

الإعدادالنطاقالافتراضي
sessionLifetimeMinutes5 – 43,200 (30 يومًا)60
maxFailedAttempts1 – 1005
lockoutDurationMinutes1 – 1,440 (24 ساعة)10
Session and lockout settings with numeric inputs for session lifetime, max failed attempts, and lockout duration

ضبط الجلسة والإقفال

خطافات الويب

تتيح لك خطافات الويب التفاعل مع أحداث المصادقة في الوقت الفعلي. هناك حدثان (onUserAuthenticated وonTokenIssued) قابلان للفرض، فهما يُطلَقان افتراضيًا بشكل غير متزامن ولا يحجبان المستخدم، لكن يمكنك اختيار الفرض لكل حدث بحيث ترفض الإجراءَ استجابةٌ خارج نطاق 2xx أو جسمُ {"allow": false}. أما الأحداث المتبقية فهي إشعارات تُطلَق دائمًا بأسلوب إطلاق ونسيان، ولا تحجب أبدًا.

الحدثالنوعالوصف
onUserAuthenticatedقابل للفرضيُطلَق بعد تسجيل دخول ناجح. يكون افتراضيًا بأسلوب إطلاق ونسيان حتى لا يتأثر زمن استجابة تسجيل الدخول. بدّل <code>webhookEnforceUserAuthenticated</code> لجعله حاجبًا، فعندئذٍ ترفض تسجيلَ الدخول استجابةٌ خارج نطاق 2xx أو جسمُ <code>{"allow": false}</code>.
onTokenIssuedقابل للفرضيُطلَق قبل سَكّ الرموز (authorization_code وrefresh_token وclient_credentials). يكون افتراضيًا بأسلوب إطلاق ونسيان. بدّل <code>webhookEnforceTokenIssued</code> لجعله حاجبًا، فعندئذٍ تمنع إصدارَ الرمز استجابةٌ خارج نطاق 2xx أو جسمُ <code>{"allow": false}</code>.
onUserCreatedإشعارإشعار بأسلوب إطلاق ونسيان عند تسجيل مستخدم جديد أو تزويده عبر SCIM.
onUserUpdatedإشعارإشعار بأسلوب إطلاق ونسيان عند تحديث سجل مستخدم (تغييرات الملف الشخصي، تغييرات الأدوار، تحديثات SCIM).
onUserDeletedإشعارإشعار بأسلوب إطلاق ونسيان عند حذف مستخدم، سواء عبر البوابة/SCIM أو بحكم سياسة الاحتفاظ.
onLoginFailedإشعارإشعار بأسلوب إطلاق ونسيان عند فشل محاولة تسجيل دخول بسبب بيانات اعتماد خاطئة أو إقفال أو رفض من السياسة.

إعدادات إضافية لخطافات الويب:

الإعدادالنطاقالافتراضيالوصف
webhookTimeoutSeconds1 – 305أقصى مدة انتظار لاستجابة خطاف ويب خاص بالفرض قبل انتهاء المهلة
webhookFailOpenمُفعّل / معطّلمُفعّلعند التفعيل، إذا تعذّر الوصول إلى خطاف ويب خاص بالفرض أو انتهت مهلته، يُسمح بمتابعة العملية
Webhook configuration section showing URL inputs for each event type, timeout slider, and fail-open toggle

ضبط أحداث خطاف الويب

توفر خطاف الويب الخاص بالفرض

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

التحقق من خطافات الويب

بمجرد ضبط أي عنوان URL لخطاف ويب، يَسُكّ Authagonal سرّ توقيع خاصًا بكل مستأجر (قيمة whsec_… تُعرض للقراءة فقط ضمن الإعدادات ← خطافات الويب). يحمل كل تسليم صادر ترويسة X-Authagonal-Signature: t=<unix>,v1=<hex>، حيث يكون v1 هو HMAC-SHA256(secret, "{t}.{body}") محسوبًا على جسم الطلب الخام. أعِد حسابه على نقطة النهاية لديك وقارنه بزمن ثابت للتأكد من أن الطلب وارد فعلًا من Authagonal ولم يُعبَث به، وارفض عمليات التسليم التي تكون قيمة t فيها قديمة جدًا لمنع هجمات إعادة التشغيل.

التحقق من خطاف ويب (Node.js)
import crypto from 'node:crypto';

// rawBody MUST be the exact bytes Authagonal sent: verify before any JSON re-serialization.
function verifyAuthagonalWebhook(signatureHeader, rawBody, signingSecret) {
  const parts = Object.fromEntries(signatureHeader.split(',').map((p) => p.split('=')));
  const { t, v1 } = parts;

  // Replay protection: reject deliveries older than 5 minutes.
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;

  const expected = crypto
    .createHmac('sha256', signingSecret)
    .update(`${t}.${rawBody}`)
    .digest('hex');

  return v1.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}

تدوير سرّ التوقيع

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

نافذة الصيانة

حدّد نافذة صيانة مفضّلة للعمليات المعطِّلة مثل نقل بيانات مستأجرك بين أجزاء التخزين. اختر ساعة بتوقيت UTC (من 0 إلى 23)، وتعرض البوابة أيضًا التوقيت المكافئ في منطقتك الزمنية المحلية للتيسير.

التسجيل والوصول

من يُسمح له بأن يصبح مستخدمًا في مستأجرك، وبأي شروط يمكنه تسجيل الدخول.

الإعدادالافتراضيالوصف
التسجيل العاممُفعّلما إذا كان بإمكان أي شخص تسجيل نفسه. إيقافه يخفي صفحة التسجيل ويرفض واجهة API الخاصة بالتسجيل، وهذا مهم: فإخفاء الرابط وحده كان سيترك نقطة النهاية مفتوحة. استخدمه حين تزوّد المستخدمين بنفسك عبر SCIM أو واجهة API أو الدعوات.
اشتراط التحقق من البريد الإلكتروني لتسجيل الدخولمُفعّللا يستطيع العنوان غير المؤكَّد تسجيل الدخول. عطّله إن كان تطبيقك أنت هو من يشترط التحقق بدلًا من ذلك، فمطالبة email_verified تبقى محمولة في الرمز في الحالتين، وبذلك تحتفظ بالإشارة.
التسجيل الديناميكي للعملاءمعطّليتيح للعميل تسجيل نفسه أثناء التشغيل وفق RFC 7591، وهو ما يحتاجه وكيل ذكاء اصطناعي أو موصّل MCP قبل أن يبدأ أي تدفق. معطّل افتراضيًا، وتفعيله يفتح الباب لمستأجرك وحده. وتبقى عمليات التسجيل محدودة المعدل ومشترِطة PKCE ومشترِطة الموافقة في كل الأحوال.
سياسة MFA للبوابةمعطّلةالمصادقة متعددة العوامل لفريقك أنت عند تسجيل الدخول إلى البوابة، وتُضبط بمعزل عن السياسة الخاصة بمستخدميك النهائيين. معطّلة، أو معروضة عند تسجيل الدخول، أو إلزامية.
الحد الأقصى للمستخدمينبدونلا يوجد سقف لإجمالي المستخدمين افتراضيًا، ولا تفرض أي خطة سقفًا. وما دام عنوان البريد الإلكتروني لمالك المستأجر غير مُتحقَّق منه، يُطبَّق سقف مؤقت قدره 5 مستخدمين، ويُرفع نهائيًا بمجرد التحقق من العنوان.

الاحتفاظ بالمستخدمين غير النشطين

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

الإعدادالافتراضيالوصف
التعطيل بعد (أيام من عدم النشاط)أبدًايعطّل الحساب الذي لم يسجّل الدخول طوال هذه المدة. ويُحتفظ بالسجل ويمكن إعادة تفعيله.
الحذف بعد (أيام من عدم النشاط)أبدًايحذف الحساب نهائيًا. ولا يوجد تراجع، لذا اضبط نافذة التحذير وخطاف الويب أدناه قبل تفعيل هذا الإعداد.
أيام التحذير7عدد الأيام التي يُطلَق فيها خطاف ويب التحذير قبل التعطيل أو الحذف، بما يمنحك وقتًا للتدخل.
خطاف ويب الاحتفاظ-المكان الذي تُرسَل إليه تلك التحذيرات والإجراءات المنفَّذة، حتى تتمكن من إخطار الشخص أو إبقاء الحساب مفتوحًا.

تصدير التدقيق والنسخ الاحتياطية البعيدة

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

بيئات الاختبار

تدير صفحة البيئات بيئات الاختبار: بيئات مُسمّاة ومعزولة لكل منها مستخدموها وعملاؤها ومفاتيح التوقيع وتسجيلات MFA والمنح الخاصة بها، ويمكن الوصول إلى كل منها على عنوان URL منفصل. أما العلامة التجارية والخطة والفوترة فمشتركة مع البيئة الفعلية. استخدمها لاختبار تغييرات الإعداد وتكاملات SSO ونقاط نهاية خطافات الويب دون التأثير على المستخدمين الفعليين. يمكنك إنشاء ما يصل إلى 5 بيئات افتراضيًا، ويُحتسب مستخدمو بيئات الاختبار النشطون ضمن MAU لديك.

الإجراءالوصف
إضافة بيئةينشئ بيئة جديدة. يتكوّن الاسم من 1 إلى 20 حرفًا من الأحرف اللاتينية الصغيرة والأرقام، والاسم "live" محجوز. تبدأ البيئة فارغة: لا يُنسخ أي شيء من البيئة الفعلية.
تحديثيمسح بيانات البيئة ويعيد ضبطها إلى حالة فارغة.
حذفيحذف بيئة الاختبار وجميع بياناتها نهائيًا.

يمكن الوصول إلى كل بيئة على {name}-{slug}.authagonal.io.

Environments page listing sandbox environments with their URLs and Refresh and Delete actions

عناصر التحكم في بيئة الاختبار

الفوترة

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

معلومات الاشتراك

تعرض صفحة الفوترة تفاصيل اشتراكك الحالي بنظرة واحدة. سترى شارة حالة تشير إلى وضع اشتراكك (active أو trialing أو past_due أو canceled أو unpaid)، إلى جانب اسم خطتك وفترة الفوترة الحالية (تاريخا البدء والانتهاء) وما إذا كان اشتراكك مضبوطًا للإلغاء في نهاية الفترة الحالية.

إدارة الاشتراك

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

إذا لم يكن هناك اشتراك بعد، يظهر بدلًا من ذلك زر دعوة لاتخاذ إجراء إعداد الفوترة، يرشدك خلال اختيار خطة وإدخال تفاصيل الدفع.

Billing page showing subscription status, plan name, billing period, and Manage Subscription button

تعرض صفحة الفوترة تفاصيل اشتراكك الحالي وتتيح الوصول إلى Stripe

أمان الدفع

تُدار جميع عمليات الفوترة عبر Stripe. لا تُخزَّن معلومات الدفع الخاصة بك أبدًا على خوادم Authagonal.

النطاقات المخصصة

قدّم صفحات المصادقة من نطاقك الخاص (مثل auth.yourdomain.com) بدلاً من النطاق الافتراضي {slug}.authagonal.io. تمنح النطاقات المخصصة مستخدميك تجربة مصادقة سلسة تحمل علامتك التجارية.

إضافة نطاق

أدخل اسم المضيف الذي تريد استخدامه في نموذج إضافة النطاق (مثل auth.yourdomain.com). بمجرد إضافته، سيظهر النطاق في قائمة نطاقاتك بحالة pending_verification.

التحقق عبر DNS

أنشئ سجلَّي CNAME اللذين تعرضهما البوابة للنطاق، وكلاهما يشير إلى {slug}.authagonal.io: أحدهما على اسم المضيف نفسه، وهو الذي يخدم حركة المرور ويمكن تمريره عبر وكيل (proxy)، والآخر على _authagonal-challenge. متبوعًا باسم المضيف، وهو الذي يثبت الملكية ويجب أن يكون DNS فقط (بدون وكيل). بمجرد إضافة السجلات، انقر على فحص DNS للتحقق. كما يُعاد فحص النطاقات المعلّقة تلقائيًا.

CNAME records
auth.yourdomain.com.                        CNAME  acme.authagonal.io.
_authagonal-challenge.auth.yourdomain.com.  CNAME  acme.authagonal.io.

انتشار DNS

قد يستغرق انتشار DNS ما يصل إلى 48 ساعة. إذا فشل التحقق، انتظر وحاول مرة أخرى.

شهادات TLS

بمجرد التحقق من نطاقك، تحتاج إلى شهادة TLS كي يتمكن المستخدمون من الاتصال بأمان عبر HTTPS. يدعم Authagonal خيارين:

تلقائي (cert-manager) يوفّر Authagonal شهادات TLS ويجدّدها تلقائياً باستخدام cert-manager. هذا هو الخيار الموصى به لمعظم المستخدمين، ولا يتطلب أي إعداد إضافي.

أحضر شهادتك الخاصة (BYO) ارفع شهادتك ومفتاحك الخاص بصيغة PEM. هذا الخيار مفيد إذا كانت مؤسستك تتطلب شهادات من جهة إصدار شهادات محددة. ويتم تتبّع انتهاء صلاحية الشهادة كي تتمكن من تجديدها قبل انقضائها.

حالة النطاق

يعرض كل نطاق شارة حالة تشير إلى وضعه الحالي: pending_verification (لم يُؤكَّد DNS بعد)، أو verified (تم تأكيد DNS وما زال TLS قيد الانتظار)، أو active (يعمل بالكامل).

Domain list showing domains with status badges and verification controls

تعرض قائمة النطاقات كل نطاق مخصص وحالته الحالية

BYO certificate upload form with certificate and private key PEM fields

ارفع شهادة TLS ومفتاحك الخاص بصيغة PEM

تجديد شهادة BYO

حافظ على تجديد شهادة BYO الخاصة بك. ستتسبب الشهادات منتهية الصلاحية في ظهور تحذيرات أمان للمتصفح لمستخدميك.

المنظمات

المنظمة هي عميل داخل مستأجر. ويظل المستأجر حدّ العزل: بادئة جداول واحدة ومفتاح توقيع واحد، وكل مضيف للمستأجر هو مُصدِر مستقل. أما المنظمة فتقسّم الهوية داخله، بحيث يخدم مستأجر واحد منظمات عملاء كثيرة دون مستأجر لكل عميل.

تعمل المنظمات جنبًا إلى جنب مع النطاقات المخصصة (يمكن تثبيت نطاق على منظمة واحدة) وتطبيقات التزويد (يمكن لتطبيق التزويد وسم مستخدم جديد بمنظمة). راجع دليل تطبيقات متعددة العملاء للاطلاع على النمط الكامل «مستأجر واحد، وعملاء كثيرون بعلامات تجارية مختلفة» الذي وُجدت هذه الميزة من أجله.

النموذج والمعرّفات

لكل منظمة id ثابت لا يتغير (بالشكل org_<32 hex>) يُصدَر كمطالبة الرمز org_id، وslug ثابت وفريد داخل المستأجر يُصدَر كـ org_slug ويقبله معامل التفويض organization. تشترك المعرّفات وslugs في فضاء بحث واحد: فأي slug يطابق معرّف منظمة أخرى يُرفض باعتباره تعارضًا، تمامًا مثل slug مكرر عادي.

الحقلقابل للتعديلالوصف
idلامطالبة org_id. يُنشأ بالصيغة org_ + GUID. والشرطة السفلية غير مسموح بها في slug، لذا لا يمكن أن يتعارض معرّف جديد مع slug.
slugلامطالبة org_slug، وهو ما يقبله معامل organization. ثابت لأن الطرف المعتمِد (relying party) يكتبه في شيفرته مباشرة.
nameنعممطالبة <code>org_name</code>. قابلة للتعديل بحرية.
metadataنعمأزواج مفتاح/قيمة حرة يتحكم بها المستأجر. لا تُصدَر في أي رمز ما لم تُفصح مجموعة مطالبات نطاق (scope) صراحةً عن واحد منها.
brandingJsonنعمكائن JSON يُدمج حقلًا بحقل فوق العلامة التجارية للمستأجر، راجع «تجاوز العلامة التجارية» أدناه.
domainsعبر نقاط نهاية النطاقات فقطنطاقات البريد الإلكتروني التي طالبت بها المنظمة، لكل منها سجل DNS الذي يثبت ملكيته. لا تتغير إلا عبر نقاط نهاية النطاقات أدناه، ولا تتغير أبدًا بالتحديث.

العضويات

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

الحالةهل تمنح رموزًا؟
invitedتمت دعوته ولم يقبل بعد. لا يجيز إصدار الرموز.
activeعضو في وضع سليم. وهي الحالة الوحيدة التي تجيز إصدار الرموز.
suspendedسُحبت العضوية دون حذف السجل. لا تجيز إصدار الرموز.

تُسحب roles العضوية من فهرس الأدوار الموجود في المستأجر وتُدمج في مطالبة roles، لكن فقط عندما تكون المنظمة قد حُدّدت صراحةً بواسطة الطلب (راجع تحديد المنظمة في الرمز) ومن صف عضوية نشطة فقط. ولا يصل دور يُشغَل في منظمة إلى رمز صادر لمنظمة أخرى أبدًا.

الدعوة إلى منظمة

يقبل POST /api/v1/users/invite المعاملين الاختياريين organizationId وorganizationRoles. ينشئ استدعاء واحد الحساب بعضوية invited ويرسل بريد دعوة يحمل العلامة التجارية للمنظمة. ويُفتح الرابط على النطاق المخصص المثبّت للمنظمة إن كان لديها نطاق. وعندما يقبل الشخص الدعوة تصبح العضوية active. وتسمية منظمة تتطلب دور مالك أو مسؤول.

تزويد SCIM داخل منظمة

يمكن ربط رمز SCIM بمنظمة (organizationId في POST /api/v1/scim/tokens، أو منتقي المنظمة عند إنشاء رمز). ويجب أن يسمّي المعرّف منظمة موجودة في المستأجر. كل مستخدم ينشئه ذلك الرمز يصبح عضوًا active ويحمل المنظمة كـ org_id. ويُطبَّق الربط عند الإنشاء فقط، وهو يحدد العضوية لا الوصول: فرمزان على عميل واحد يريان مستخدمي بعضهما. وحذف مستخدم، بأي طريقة، يزيل عضوياته.

أعلام السياسة

enabled (مفعّل افتراضيًا): المنظمة المعطّلة لا تُصدر رموزًا لنفسها، ويُتحقق من ذلك عند التفويض وعند كل تجديد، فيوقف تعطيل منظمة الجلسات الحية عند دورة التدوير التالية بدلًا من منع تسجيلات الدخول الجديدة فقط.

requireMembershipForTokens (مفعّل افتراضيًا): يحدد ما إذا كان على المستخدم أن يحمل عضوية نشطة ليُصدَر له رمز لهذه المنظمة. ولا يسري إلا على التحديد الصريح (طلب يسمّي المنظمة، أو تجديد يحملها، أو اتصال مقيّد بمنظمة، أو عميل مقيّد بمنظمة واحدة بالضبط). أما المنظمة الموروثة من الوسم القديم للحساب فحسب فلا يقيّدها هذا العلم أبدًا.

يتيح allowAutoMembership (معطّل افتراضيًا) للمستخدم الانضمام دون دعوة عندما يكون عنوان بريده الإلكتروني المؤكَّد ضمن أحد نطاقات المنظمة الموثَّقة. ويُطبَّق عند التفويض وعند كل تجديد. راجع «نطاقات البريد الإلكتروني والعضوية التلقائية» أدناه.

نطاقات البريد الإلكتروني والعضوية التلقائية

تطالب المنظمة بنطاق بريد إلكتروني وتثبت تحكمها به بسجل DNS من نوع TXT. وعند تفعيل allowAutoMembership، يصبح المستخدم الذي يقع بريده الإلكتروني المؤكَّد ضمن ذلك النطاق عضوًا عند أول تسجيل دخول له بصفته المنظمة.

  1. المطالبة به. أرسل POST /api/v1/organizations/{id}/domains مع النطاق. الاستجابة 201 مع recordName (_authagonal-org.acme.com) وrecordValue (authagonal-org-verify=<token>). الرمز عشوائي ولكل مطالبة رمزها.
  2. انشر السجل. أضف سجل TXT بذلك الاسم وبالقيمة نفسها تمامًا في DNS الخاص بالنطاق.
  3. تحقق منه. يبحث POST /api/v1/organizations/{id}/domains/{domain}/verify عن السجل. وعند التطابق يعيد 200 مع verified: true. وعند عدم التطابق يعيد 409 verification_failed، وليس 200 مع verified: false أبدًا، فلا يخلط عميل يستطلع النجاح بين الإخفاق والنجاح.
  4. أزله. يعيد DELETE /api/v1/organizations/{id}/domains/{domain} الاستجابة 204. تبقى العضويات الحالية، ويتوقف فقط الانضمام التلقائي مستقبلًا.
POST /api/v1/organizations/{id}/domains
POST /api/v1/organizations/org_7fa2c9e1.../domains
Content-Type: application/json

{ "domain": "acme.com" }

201 Created
{
  "domain": "acme.com",
  "verified": false,
  "verifiedAt": null,
  "createdAt": "2026-10-03T01:02:03Z",
  "recordName": "_authagonal-org.acme.com",
  "recordValue": "authagonal-org-verify=Qm9...base64url"
}

حالات الرفض: 400 domain_invalid (ليس اسم DNS مجردًا)، 409 domain_exists (موجود أصلًا في هذه المنظمة)، 409 domain_taken (تحتفظ به منظمة أخرى في المستأجر)، 404 organization_not_found و404 domain_not_found. ينتمي النطاق إلى منظمة واحدة على الأكثر لكل مستأجر، ويُفحص ذلك مرة أخرى عند التحقق.

قاعدة العضوية التلقائية

يقبل المنتقي مستخدمًا لا يحمل عضوية نشطة عندما تتحقق جميع الشروط التالية:

  • حُدّدت المنظمة صراحةً: عبر منحة تجديد محمولة، أو اتصال مقيّد بمنظمة، أو المعامل organization (يوفره تثبيت النطاق)، أو عميل مقيّد بمنظمة واحدة بالضبط. أما الوسم القديم للحساب نفسه فلا ينضم تلقائيًا أبدًا.
  • المنظمة مفعّلة وallowAutoMembership قيد التشغيل.
  • بريد المستخدم الإلكتروني مؤكَّد، لأن أي شخص يستطيع التسجيل باسم [email protected].
  • الجزء من البريد الإلكتروني بعد آخر @، بأحرف صغيرة، مطابق تمامًا لأحد نطاقات المنظمة الموثَّقة. لا توجد مطابقة للنطاقات الفرعية: فالنطاق الموثَّق acme.com لا يقبل [email protected]. طالب بكل نطاق فرعي وتحقق منه على حدة.

ما تكتبه القاعدة قبل تشغيل بوابة العضوية: إذا لم يوجد صف تصبح عضوية active جديدة بلا أدوار؛ والصف invited يُرقّى إلى active مع الإبقاء على أدواره؛ والصف active يُترك كما هو؛ والصف suspended لا يُرقّى أبدًا.

حذف عضو لا يُبقيه خارجًا

ما دام allowAutoMembership مفعّلًا، فإن العضو المحذوف الذي ما زال مؤهلًا ينضم من جديد عند التفويض أو التجديد التالي. ولإبقاء مستخدم مؤهل خارجًا، اضبط عضويته على suspended، وهي الحالة الوحيدة التي لا تغيّرها القاعدة.

تحديد المنظمة في الرمز

المنظمة التي يُحَلّ إليها الطلب تُحدَّد في مكان واحد بالضبط، فتكون النتيجة نفسها في /connect/authorize وعند كل تجديد وفي منحة الجهاز. الأسبقية من الأعلى إلى الأدنى:

#المصدرالسلوك
1المنحة المحمولة (التجديد)المنظمة التي صدر لها رمز سابق. وإن لم تعد موجودة يُرفض التجديد نفسه بدلًا من الرجوع إلى أي شيء آخر.
2اتصال مقيّد بمنظمةالجلسة سجّلت الدخول عبر اتصال SAML أو OIDC يتبع منظمة واحدة، فتُحدَّد تلك المنظمة. وهو المصدر الوحيد الذي يكون مثبتًا لا مجرد مُدّعى. ويُرفض الطلب الذي يسمّي منظمة مختلفة، وكذلك الاتصال الذي لم تعد منظمته موجودة.
3organizationيُحَلّ بالـ slug أولًا ثم بالمعرّف. ويصل تثبيت النطاق إلى هذا الفرع نفسه: إذ يُلحقه الوسيط (middleware) قبل تقييم الطلب. وتسمية منظمة غير موجودة رفض قاطع، وليست رجوعًا صامتًا إلى بديل.
4عميل مقيّد بمنظمة واحدة بالضبطيُحدَّد تلقائيًا: يسجّل التطبيق الخاص بكل عميل منظمته الوحيدة مرة واحدة ولا يرسل معاملًا أبدًا. أما المقيّد بأكثر من منظمة <em>واحدة</em> دون تلميح فيُرفض بالخطأ <code>account_selection_required</code>.
5وسم المنظمة القديم للحساب نفسهسلسلة نصية مسطحة واحدة تُحَلّ بالمعرّف في بحث واحد، وليست مسحًا لعضويات المستخدم. وإن لم تسمِّ أي صف منظمة حقيقي فتُصدَر كما هي حرفيًا دون أي تقييد، تمامًا كما كان الحال قبل وجود المنظمات. وهي ليست تحديدًا صريحًا أبدًا، لذلك لا تنضم تلقائيًا أبدًا.
6لا شيء مما سبقلا توجد منظمة على الرمز إطلاقًا: لا مطالبة <code>org_id</code> أو <code>org_slug</code> أو <code>org_name</code>.

العضويات ليست تلميحًا أبدًا

المستخدم الذي لديه عدة عضويات نشطة وطلبه لا يسمّي أي منظمة يتصرف بالطريقة نفسها تمامًا كمستخدم بلا عضويات: لا يُرجَع إلى جدول العضويات لاختيار قيمة افتراضية. ينتقل التحديد مباشرة إلى الوسم القديم للحساب نفسه (الصف 5)، وإن كان فارغًا أيضًا فلا يحمل الرمز أي منظمة. ولا تبدأ العضويات في الأهمية إلا بعد تسمية منظمة صراحةً، وعندها يُفحص requireMembershipForTokens وتُجرَّب العضوية التلقائية إن انطبقت.

تثبيت النطاق

يمكن تثبيت نطاق مخصص على منظمة واحدة، ليصبح ذلك النطاق الباب الأمامي الخاص بالمنظمة. ويُفرض التثبيت بواسطة وسيط تحديد المستأجر (tenant-resolution middleware) لكل من GET /connect/authorize (يُلحق بسلسلة الاستعلام) وPOST /connect/par (يُعاد كتابة الجسم المدفوع بدلًا من ذلك، لأن PAR يقرأ معاملاته من الحمولة المخزّنة). راجع النطاقات المخصصة للاطلاع على الآلية الكاملة.

PUT /api/v1/custom-domains/{domain}/organization
PUT /api/v1/custom-domains/auth.acme.com/organization
Content-Type: application/json

{ "organizationId": "org_7fa2c9e1..." }

النطاق المثبّت يرفض الطلب المتعارض

الطلب الذي يسمّي منظمة مختلفة عن المثبّتة يُرفض مباشرة بـ 400 access_denied قبل عرض أي صفحة تسجيل دخول. ودون ذلك، كان بوسع الطرف المعتمِد إرسال معامل organization خاص به فيصبح التثبيت زخرفيًا فقط.

اتصالات مقيّدة بمنظمة

يمكن أن يتبع اتصال SAML أو OIDC منظمة واحدة. وتسجيل الدخول عبره يحدد تلك المنظمة وينشئ عضوية active عندما لا يكون للمستخدم عضوية. ويُقبل الصف invited: إذ يصبح active ويحتفظ بأدواره ومن دعاه، فلا يحتاج المدعو الذي يسجّل الدخول عبر IdP الخاص به إلى البريد الإلكتروني إطلاقًا. أما العضو suspended فيبقى معلّقًا ويُرفض عند إصدار الرمز. ولا يعتمد هذا على allowAutoMembership ولا على النطاقات، لأن المنظمة حُدّدت أصلًا بواسطة الاتصال.

اسم المنظمة في صفحة تسجيل الدخول

تعرض صفحة تسجيل الدخول تسجيل الدخول إلى {name} تحت اسم التطبيق. ويأتي الاسم من المنظمة نفسها التي تأتي منها العلامة التجارية للصفحة: منظمة النطاق المثبّت، ثم المنظمة التي يسميها طلب التفويض، ثم المنظمة الوحيدة المقيّد بها العميل. ويُخفى عند عدم وجود منظمة، أو عندما يساوي اسم المنظمة اسم التطبيق، فلا يظهر الترويس أبدًا بصيغة «Acme / Signing in to Acme».

تجاوز العلامة التجارية

يُدمج brandingJson الخاص بالمنظمة حقلًا بحقل فوق العلامة التجارية للمستأجر في صفحة تسجيل الدخول: المفتاح الموجود وغير الفارغ يتجاوز، والمفتاح الغائب أو الفارغ يرث، والمفتاح غير المعروف يُتجاهل. وJSON المشوَّه يعود إلى العلامة التجارية للمستأجر مع تسجيل تحذير، ولا يفشل تحميل الصفحة أبدًا.

يحرّر تبويب العلامة التجارية الحقول الـ 21 القابلة للدمج جميعها: المظهر (appName وlogoUrl وprimaryColor وcustomCssUrl)، وألوان الوضعين الفاتح والداكن، وألوان البريد الإلكتروني، وsupportEmail وshowForgotPassword وpoweredBy وlanguages. ويرث كل حقل قيمة المستأجر، وتُعرض كتلميح، أو يتجاوزها، مع عنصر تحكم «مسح» يزيل المفتاح.

لا يمكن تجاوز showRegistration

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

الترحيل من وسم المنظمة القديم

قبل وجود المنظمات كان بوسع المستخدم حمل وسم منظمة نصي حر دون أي سجل خلفه. يرحّل POST /api/v1/organizations/backfill ذلك إلى منظمات وعضويات حقيقية، مجمّعةً حسب كل قيمة قديمة مميزة. ويكون تشغيلًا تجريبيًا ما لم يكن جسم الطلب { "dryRun": false }.

  • محدود: يفحص 50,000 مستخدم كحد أقصى لكل استدعاء. والاستجابة truncated تعني أن عليك تشغيله مرة أخرى، ويُتخطى المستخدمون الذين رُحّلوا أصلًا في التشغيل التالي.
  • متكرر الأثر نفسه (idempotent): تُطابَق القيمة القديمة المميزة التي رُحّلت أصلًا بختم داخلي، لا باسم العرض (القابل للتعديل) للمنظمة، فإعادة تسمية المنظمة الناتجة لاحقًا لا تسبب تكرارًا في التشغيل التالي.
مثال على الاستجابة (تشغيل تجريبي)
{
  "dryRun": true,
  "organizationsCreated": 3,
  "membershipsCreated": 41,
  "usersSkipped": 0,
  "organizations": [
    { "legacyValue": "acme-corp", "slug": "acme-corp", "users": 22 }
  ],
  "truncated": false
}

جولة في واجهة البوابة

تسرد صفحة المنظمات كل منظمة في المستأجر، 50 في كل مرة مع زر تحميل المزيد، وتتيح منظمة جديدة (slug واسم فقط، وتُضبط أعلام السياسة والنطاقات والعلامة التجارية بعد ذلك) وتدفق ملء من حقل المنظمة القديمة الذي يشغّل الترحيل أعلاه كمعاينة، ثم «تطبيق».

Organizations list showing slug, name, and created-date columns, with New Organisation and Backfill from legacy organisation field controls

تعرض قائمة المنظمات كل منظمة عميل في المستأجر مع الـ slug والاسم وتاريخ الإنشاء

لصفحة تفاصيل كل منظمة ثلاثة تبويبات: عام (الاسم، والـ slug للقراءة فقط، ومفاتيح السياسة الثلاثة، وبطاقة نطاقات البريد الإلكتروني لإضافة نطاقات البريد الإلكتروني والتحقق منها وإزالتها ونسخ سجل TXT، وحذف يتطلب كتابة الـ slug للتأكيد)، والعلامة التجارية (كل حقل قابل للتجاوز، يرث كل منها قيمة المستأجر أو يتجاوزها)، والأعضاء (الإضافة بالبريد الإلكتروني، مع عرض دعوة عند عدم وجود حساب، وتغيير الحالة والإزالة لكل صف، مع تحميل المزيد).

Organization detail page's Members tab showing invited, active, and suspended member rows with per-row status control

يسرد تبويب الأعضاء كل عضوية مع حالتها وعنصر تحكم لكل صف لتغييرها أو إزالتها

Organization detail page's Branding tab with each overridable field showing either the tenant's inherited value or an override with a Clear control

يتجاوز تبويب العلامة التجارية علامة المستأجر في صفحة تسجيل الدخول حقلًا بحقل لهذه المنظمة

تحمل صفحة النطاقات المخصصة منتقي النطاق ← المنظمة: لكل بطاقة نطاق قائمة منسدلة مضمّنة تسرد منظمات المستأجر بالإضافة إلى خيار «مستأجر (بدون)» الذي يمسح التثبيت، ويُطبَّق فور التغيير. ويظهر المنتقي نفسه عند إضافة نطاق.

Domain card showing the inline organisation selector that pins a custom domain to one organisation

منتقي المنظمة المضمّن في بطاقة النطاق يثبّت ذلك النطاق المخصص على منظمة واحدة

أحداث التدقيق

organization.created · organization.updated · organization.deleted · organization.member.added · organization.member.invited · organization.member.joined · organization.member.updated · organization.member.removed · organization.domain_added · organization.domain_verified · organization.domain_removed · organization.backfill · domain.organization_set

التصفح بالصفحات

قائمة المنظمات وقائمة الأعضاء مقسّمتان بمؤشر (cursor) وتعيدان { items, nextCursor }. مرّر limit (الافتراضي 50، ويُقيَّد بين 1 و200) وبعد الصفحة الأولى مرّر nextCursor من الاستجابة السابقة دون تغيير كـ cursor. وقيمة nextCursor الفارغة تعني الصفحة الأخيرة. والمؤشر موضع مفتاحي معتم على معرّف المنظمة (أو معرّف المستخدم للأعضاء)، لذا فإضافة صفوف أو إزالتها بين الاستدعاءات لا تُزيح صفحة ولا تكررها. والمؤشر الذي لم تصدره القائمة هو 400 invalid_cursor.

إدارة المنظمات من مساعد ذكاء اصطناعي

يعرض MCP البوابة المستضاف ثلاث عشرة أداة للمنظمات، وكلها تتطلب دور مسؤول المستأجر: عرض المنظمات وجلب واحدة وإنشاؤها وتحديثها وحذفها؛ وعرض الأعضاء وإضافتهم وتحديثهم وإزالتهم؛ وإضافة نطاقات البريد الإلكتروني والتحقق منها وإزالتها؛ وعرض منظمات مستخدم. وتستدعي العمليات نفسها التي يستدعيها API أعلاه، فلا يمكن لأداة أن تنحرف عن مسارها. راجع شغّل بوابتك من مساعد ذكاء اصطناعي.

مُصدِر واحد لكل مضيف

كل مضيف للمستأجر هو مُصدِر OIDC مستقل. وعندما يُحَلّ مضيف الطلب عبر جدول نطاقات المستأجر، يكون المُصدِر وكل عنوان URL لنقطة نهاية يعلن عنها الاكتشاف هو https://{host}، فيؤكد كل نطاق مخصص نشط iss الخاص به ويبقى مضيف المستأجر الأساسي دون تغيير. مفاتيح التوقيع لكل مستأجر، لذا يقدّم كل مضيف مجموعة المفاتيح نفسها. وهذا ما يتيح لمستأجر واحد أن يخدم عدة عملاء، كلٌّ على نطاقه المخصص بعلامته التجارية والمثبّت على منظمته. راجع النطاقات المخصصة.

إعداد البريد الإلكتروني

اضبط طريقة إرسال المستأجر الخاص بك للرسائل البريدية المعاملاتية، مثل رسائل التحقق وإعادة تعيين كلمة المرور والدعوة. اختر بين المرسِل المشترك الافتراضي، أو نطاق مخصص مُتحقَّق منه عبر Resend، أو خادم SMTP الخاص بك.

Email settings showing provider options (default, Resend domain, custom SMTP) and a test-send

الرسائل البريدية المترجَمة

تُرسَل الرسائل البريدية المعاملاتية بلغة المستلِم المفضّلة. تُصمَّم قوالب رسائل التحقق وإعادة تعيين كلمة المرور وتنبيه وجود الحساب والترحيب والدعوة وحذف الحساب والدعم والفوترة بإحدى عشرة لغة: الإنجليزية والألمانية والفرنسية والإسبانية والبرتغالية والفيتنامية والصينية المبسّطة واليابانية والعربية والهندية والأفريكانية. وعند عدم توفر قالب بلغة المستلِم، يعود البريد إلى الإنجليزية.

تُحدَّد اللغة من تفضيل المستلِم المخزَّن عند الإرسال. ويمكن أن يأتي هذا التفضيل من عدة مصادر:

  • التسجيل وإنشاء الحساب يُلتقط من اللغة التي اختارها المستخدم على شاشات تسجيل الدخول المُستضافة.
  • صفحة المستخدمين في البوابة يضبطها المسؤول عند إنشاء مستخدم أو تعديله.
  • التزويد عبر SCIM: يُحدَّد من preferredLanguage (أو locale) الخاص بمزوّد الهوية عند مزامنة المستخدمين عبر SCIM.
  • صفحة الحساب ذاتية الخدمة يختارها المستخدم بنفسه عبر /login/account.

لا حاجة إلى أي إعداد

الترجمة تلقائية وتنطبق على كل أوضاع المزوّدين (الافتراضي، ونطاق Resend المخصص، وSMTP). ولا يوجد ما يلزم تفعيله.

مزوّدو البريد الإلكتروني

المزوّدالوصفالإعداد
Authagonal (Default)تُرسَل الرسائل من [email protected] باستخدام بنية Resend المشتركة لدينا.لا حاجة إلى أي إعداد، يعمل مباشرةً وبشكل جاهز.
Custom Domain (Resend)تُرسَل الرسائل من نطاقك الخاص المُتحقَّق منه عبر Resend.سجّل نطاقك، وأضف سجلات DNS، وتحقق من الملكية.
Custom SMTPتُرسَل الرسائل عبر خادم SMTP الخاص بك.قدّم مضيف SMTP والمنفذ وبيانات الاعتماد وإعدادات TLS.

هوية المرسِل

بريد المرسِل واسمه مشتركان عبر جميع أوضاع المزوّدين. بريد المرسِل مطلوب لمزوّدَي نطاق مخصص (Resend) وSMTP مخصص، ويعود اسم المرسِل إلى اسم التطبيق في العلامة التجارية عند تركه فارغاً.

الحقلالوصف
emailSenderEmailعنوان "من" في الرسائل الصادرة. يجب أن يكون على نطاق مُتحقَّق منه في وضع نطاق مخصص (Resend).
emailSenderNameالاسم المعروض في صندوق وارد المستلِم.

نطاق Resend المخصص

تحقق من نطاق الإرسال الخاص بك مع Resend مرة واحدة، ثم استخدمه كعنوان "من" لهذا المستأجر. تُعرض سجلات DNS (SPF وDKIM) في لوحة نطاق إرسال مخصص ضمن الإعدادات ← البريد الإلكتروني، ويتحقق منها Resend عند النقر على <strong>التحقق من الإثبات</strong>.

SMTP مخصص

أحضر خادم SMTP الخاص بك، وهو مفيد لعمليات الترحيل الداخلية، أو للمزوّدين غير المشمولين بـ Resend، أو للتثبيت التنظيمي.

الحقلالوصف
smtpHostاسم مضيف خادم SMTP (مثل smtp.example.com).
smtpPortمنفذ الاتصال، والقيمة الافتراضية 587. يُتفاوض على TLS عبر STARTTLS، ولا يُدعم TLS الضمني على المنفذ 465. استخدم 25 لعمليات الترحيل الداخلية غير المصادَق عليها.
smtpUsernameاسم مستخدم المصادقة (اختياري، اتركه فارغاً لعمليات الترحيل غير المصادَق عليها).
smtpPasswordكلمة مرور المصادقة. تُخزَّن مشفّرة في سر إعدادات المستأجر.
smtpUseTlsاشترط TLS. اتركه مُفعَّلاً ما لم تكن تستهدف عملية ترحيل داخلية موثوقة.

نطاق إرسال مخصص

عند استخدام مزوّد نطاق مخصص (Resend)، يمكنك تسجيل نطاقك الخاص كي تصدر الرسائل من علامتك التجارية (مثل [email protected]) بدلاً من @authagonal.io.

  1. اذهب إلى الإعدادات ← البريد الإلكتروني واختر مزوّد نطاق مخصص (Resend).
  2. أدخل اسم نطاقك وانقر على تسجيل النطاق.
  3. أضف سجلات DNS المعروضة (DKIM وSPF ومسار الإرجاع) إلى DNS الخاص بنطاقك.
  4. انقر على التحقق من الإثبات، وبمجرد انتشار DNS (عادةً خلال 1 إلى 10 دقائق)، ستتغير حالة النطاق إلى مُتحقَّق منه.

انتشار DNS

قد تستغرق تغييرات DNS ما يصل إلى 48 ساعة لتنتشر عالمياً، وإن كان معظم المزوّدين يحدّثونها خلال دقائق. يمكنك التحقق من الإثبات بقدر ما تحتاج.

الاختبار

استخدم زر إرسال بريد اختباري في الإعدادات ← البريد الإلكتروني للتحقق من إعدادك. سيُرسَل بريد اختباري إلى عنوان بريد المسؤول الخاص بك باستخدام الإعدادات المحفوظة حالياً.

سجل التدقيق

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

أعمدة السجل

العمودالوصف
الطابع الزمنيتاريخ ووقت وقوع الإجراء
المنفِّذعنوان البريد الإلكتروني للمسؤول الذي نفّذ الإجراء، أو "system" للإجراءات الآلية
الإجراءنوع الإجراء المنفَّذ (مثل: إنشاء عميل، تحديث الإعدادات)
الكيانهدف الإجراء بصيغة type:id (مثل: client:my-app)
التفاصيلسياق إضافي حول التغيير

الإجراءات المتتبَّعة

تُسجَّل الإجراءات الإدارية التالية في سجل التدقيق:

الفئةالإجراءات
العملاءإنشاء عميل، تحديث عميل، حذف عميل
اتصالات SSOإنشاء اتصال SAML، حذف اتصال SAML، إنشاء اتصال OIDC، حذف اتصال OIDC
المستخدمونإنشاء مستخدم، تحديث مستخدم
الإعداداتتحديث الإعدادات، تحديث العلامة التجارية
النطاقاتإضافة نطاق، التحقق من نطاق، حذف نطاق
SCIMإنشاء رمز SCIM، إبطال رمز SCIM
الأدوارإنشاء دور، تحديث دور، حذف دور
المجموعاتإنشاء مجموعة، حذف مجموعة
الفريقدعوة عضو فريق، إزالة عضو فريق
Audit log table showing timestamped administrative actions with actor, action, entity, and detail columns

يوفّر سجل التدقيق سجلاً متكاملاً لجميع الإجراءات الإدارية

الاحتفاظ

يُحتفظ بسجلات التدقيق لمدة 365 يومًا، ولا يمكن تعديلها أو حذفها. للاحتفاظ بها مدة أطول، فعّل التصدير التلقائي من تبويب التصدير بصفحة سجل التدقيق.

النسخ الاحتياطي

ينشئ Authagonal نسخاً احتياطية من بيانات المستأجر الخاص بك تلقائياً وفق جدول يعمل كل ساعة. تشمل النسخ الاحتياطية جميع المستخدمين والمجموعات والأدوار والعملاء واتصالات SSO ورموز SCIM والعلامة التجارية والإعدادات. ويمكنك عرض سجل النسخ الاحتياطي وتنزيل أحدث نسخة احتياطية كاملة من صفحة النسخ الاحتياطي.

Backups page showing backup history with timestamps, types, and entity counts

كيف يعمل النسخ الاحتياطي

  • مرة يوميًا تُدمج النسخ التزايدية التي تُجرى كل ساعة في نسخة احتياطية كاملة جديدة، وفي أيام الأحد تُدمج النسخ الكاملة اليومية في نسخة احتياطية أسبوعية. ويُحتفظ بسبع نسخ يومية وأربع نسخ أسبوعية.
  • تُجرى النسخ الاحتياطية التزايدية كل ساعة، وتلتقط فقط الصفوف التي تغيّرت منذ آخر نسخة احتياطية.
  • تُخزَّن النسخ الاحتياطية في Azure Blob Storage بالهوية المُدارة نفسها التي يستخدمها المستأجر الخاص بك.
  • تُتتبَّع السجلات المحذوفة عبر علامات الحذف وتُدرَج في النسخ الاحتياطية اكتمالاً للتدقيق.

تنزيل النسخ الاحتياطية

انقر على تنزيل الأحدث للحصول على ملف ZIP يحتوي على أحدث نسخة احتياطية كاملة مدمجة مع جميع النسخ الاحتياطية التزايدية اللاحقة. يُصدَّر كل جدول كملف JSONL (كائن JSON واحد لكل سطر).

صيغة النسخ الاحتياطي

تُصدَّر النسخ الاحتياطية بصيغة JSONL (سطور JSON)، أي كيان واحد لكل سطر لكل جدول. هذه الصيغة سهلة التحليل والمقارنة والاستيراد إلى أنظمة أخرى.

تطبيقات التزويد

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

كيف يعمل

عند إنشاء مستخدم، يستدعي Authagonal عنوان رد النداء الخاص بتطبيق التزويد لديك باستخدام نمط TCC (Try/Confirm/Cancel). يجب أن يوافق كل تطبيق في مرحلة Try قبل تثبيت أي منها، بحيث يمكن لعدة أنظمة تابعة أن تتفق، أو أن يعترض أحدها، دون ترك حسابات نصف مُنشأة.

المرحلةنقطة النهايةالغرض
/tryPOST {callbackUrl}/tryيتحقق مما إذا كان بإمكان التطبيق التعامل مع المستخدم. أعِد 200 للقبول أو 4xx للرفض.
/confirmPOST {callbackUrl}/confirmيثبّت العملية بعد أن تكون جميع التطبيقات قد قبلت مرحلة /try.
/cancelPOST {callbackUrl}/cancelيتراجع عن العملية إذا فشل تطبيق آخر أثناء مرحلة /try.

متى يعمل التزويد

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

مسار الإنشاءمتى يُستدعى
POST /api/auth/registerالتسجيل الذاتي
رد نداء SAML ACSأول تسجيل دخول عبر SSO لمستخدم جديد (JIT)
رد نداء OIDCأول تسجيل دخول عبر SSO لمستخدم جديد (JIT)
POST /scim/v2/Usersيقوم موصّل بتزويد مستخدم من دليل العميل
إنشاء المستخدمين من البوابة ولوحة الإدارةيُنشئ مشغّل مستخدمًا أو يدعوه يدويًا

طلب Try

يرسل Authagonal طلب POST بهذا الـ JSON إلى <code>{callbackUrl}/try</code>. والحقول التي لا قيمة لها تُحذف بدلًا من إرسالها بقيمة null.

الحقلالنوعالوصف
transactionIdstringيُعرّف معاملة التزويد هذه. وتُرسل القيمة نفسها إلى /confirm و/cancel، لذا جهّز عملك مرتبطًا بها ثم ثبّته أو تخلّص منه عند وصول ذلك الاستدعاء.
userIdstringمعرّف المستخدم لدى Authagonal. وهو قيمة الـ subject التي ستراها في رموزه.
emailstringعنوان البريد الإلكتروني للمستخدم.
firstNamestringالاسم الأول، إذا وفّره مسار الإنشاء.
lastNamestringاسم العائلة، إذا وفّره مسار الإنشاء.
organizationIdstringالمؤسسة التي ينتمي إليها المستخدم بالفعل، إن وُجدت. ولا يظهر هذا الحقل إلا إذا سبق لشيء ما أن خصّص مؤسسة؛ وفي أول تسجيل يكون غائبًا، وهذه إشارتك لتخصيصها.
customAttributesobjectالسمات المخصصة المخزّنة للمستخدم. وبالنسبة لمستخدم أُنشئ عبر SSO تتضمن federated_connection، وهو اسم الاتصال الذي ضمِنه.

الحالة الشائعة التي يجدر التخطيط لها هي وصول مستخدم عبر SSO: ليست لديه مؤسسة بعد، ويخبرك federated_connection بأي عميل من عملائك جاء منه.

طلب Try لمستخدم يصل عبر اتصال SSO
{
  "transactionId": "8f14e45fceea167a5a36dedd4bea2543",
  "userId": "0f6b1c8e-3d2a-4f51-9e77-2c1a4b5d6e7f",
  "email": "[email protected]",
  "firstName": "Ada",
  "lastName": "Lovelace",
  "customAttributes": {
    "federated_connection": "acme-okta"
  }
}

استجابة Try

يردّ تطبيقك بالرمز 200 وبمحتوى JSON. وهذا المحتوى ليس مجرد إقرار: فهو الطريقة التي يخصّص بها التطبيق التابع المؤسسة والسمات التي تنتهي إلى رموز المستخدم.

الحقلالنوعالوصف
approvedbooleanما إذا كان هذا التطبيق يقبل المستخدم. والقيمة الافتراضية هي true عند حذفه. أما false فيرفض التسجيل ويُحذف الحساب الجديد.
reasonstringسبب رفض المستخدم. ويُعرض على مُستدعي مسار الإنشاء.
organizationIdstringالمؤسسة التي ينتمي إليها هذا المستخدم. تُخزَّن على المستخدم وتُصدَر بوصفها المطالبة org_id في رموزه. ولا تُطبَّق إلا إذا لم تكن للمستخدم مؤسسة بالفعل، فيفوز أول تطبيق يردّ وترى التطبيقات اللاحقة ذلك التخصيص.
customAttributesobjectسمات تُدمج على المستخدم، مفتاحًا بمفتاح. وتُصدَر في الرموز من خلال إعداد UserClaims الخاص بالـ scope.
emailVerifiedbooleanيضمن تطبيقك أنه تحقق من هذا العنوان، مثلًا عبر استخدام دعوة أُرسلت إليه. عندها يضع Authagonal علامة تأكيد على الحساب ويتخطى رسالة التحقق الخاصة به.
استجابة Try تخصّص مؤسسة
{
  "approved": true,
  "organizationId": "org_acme",
  "customAttributes": { "org_role": "member" }
}

من هنا يأتي org_id

وسم المنظمة الخاص بالحساب، ومن ثمّ المطالبة org_id عندما لا يحدّد الطلب أي منظمة، هو ما أعاده تطبيق التزويد لديك في organizationId. وعندما يكون معرّف منظمة في المستأجر، تحمل الرموز org_id وorg_slug وorg_name الخاصة بتلك المنظمة، وترفض المنظمة المعطّلة تسجيل الدخول. وأي قيمة أخرى تُصدَر حرفيًا بوصفها org_id، دون قاعدة تفرّد ولا شرط تنسيق. وإعادة معرّف منظمة لا تُنشئ عضوية. ويمكنك أيضًا ضبطه مباشرة عبر PUT /api/v1/users/{userId}، والتصفية به عبر GET /api/v1/users?organizationId=.

وسم المستخدمين بالمؤسسة الصحيحة

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

تحديد المؤسسة في رد نداء Try
// POST {callbackUrl}/try
app.post('/provisioning/try', async (req, res) => {
  const { email, customAttributes } = req.body;

  // An SSO user carries the connection that vouched for them. That is the
  // customer, and it stays right when one customer has several domains.
  const connection = customAttributes?.federated_connection;

  const org = connection
    ? await orgByConnection(connection)
    : await orgByPendingInvite(email);

  if (!org) return res.json({ approved: false, reason: 'No organization for this user' });

  // Stamped on the user and emitted as org_id on every token from now on.
  res.json({ approved: true, organizationId: org.id });
});

الرفض يحذف الحساب

إذا ردّ أي تطبيق بـ approved: false، يُحذف المستخدم الذي أُنشئ للتو حتى لا يبقى حساب نصف مُزوَّد. وتُعيد مسارات الإنشاء في الـ API الرمز 422 مع قيمة reason التي قدّمتها؛ أما ردود نداء SAML وOIDC فتعيد 400. أعد approved: true للمستخدم الذي ليس لديك ما تفعله من أجله.

إضافة تطبيق تزويد

لإضافة تطبيق تزويد، قدّم اسم التطبيق وعنوان URL لاستدعاء الإرجاع ومفتاح API اختياريًا ومهلة Try اختيارية (بالثواني، القيمة الافتراضية 60، والنطاق من 5 إلى 300، بينما يستخدم Confirm وCancel مهلة قصيرة ثابتة). يُرسَل مفتاح API كرمز Bearer في ترويسة Authorization لكل طلب خطاف ويب، ما يتيح لتطبيقك مصادقة الطلبات الواردة من Authagonal.

الاختبار

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

Provisioning apps page showing configured apps with test results displaying HTTP status and response body

اختبر تطبيقات التزويد للتحقق من تسليم خطاف الويب ومعالجة الاستجابة

حدود الخطة

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

مصادقة مفتاح API

إذا تم تعيين مفتاح API، فإنه يُرسَل كرمز Bearer في ترويسة Authorization. استخدمه لمصادقة طلبات خطاف الويب الواردة من Authagonal.

الفريق

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

قائمة المسؤولين

تعرض قائمة المسؤولين اسم كل عضو في الفريق وعنوان بريده الإلكتروني ودوره وتاريخ إضافته. ويظهر مؤشر "أنت" بجوار صف المستخدم الحالي كي يسهل عليك تمييز حسابك الخاص.

دعوة المسؤولين

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

حقول الدعوة

تُنشئ دعوات المسؤولين حسابًا معلّقًا وترسل إلى المدعو رابط تفعيل عبر البريد الإلكتروني.

الحقلالوصف
emailعنوان البريد الإلكتروني للمسؤول الجديد. يجب أن يكون فريداً ضمن المستأجر.
nameالاسم المعروض في قائمة المسؤولين.
roleالدور المراد منحه: tenant:admin أو tenant:developer أو tenant:support. القيمة الافتراضية tenant:admin. ولا يمكن منح دور المالك عبر الدعوة.

إزالة المسؤولين

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

Team page showing the admin list with name, email, date added columns, a You indicator, and invite/remove controls

إدارة مسؤولي البوابة من صفحة الفريق

الملكية

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

الدعم

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

تذاكرك

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

Support ticket list showing each ticket's subject, status badge, priority, and last-activity time, with a New ticket button

تذاكر الدعم الخاصة بك مع الموضوع والحالة والأولوية وآخر نشاط

  • يعرض كل صف الموضوع والحالة الحالية (مفتوحة، أو قيد الانتظار، أو محلولة، أو مغلقة) والأولوية ووقت آخر نشاط.
  • انقر على تذكرة جديدة لفتح واحدة، ثم امنحها موضوعاً وأولوية ورسالتك الأولى.
  • تسهّل شارات الحالة المُرمَّزة بالألوان مسح القائمة بحثاً عن التذاكر التي تحتاج إلى انتباهك.

سلسلة التذكرة

يعرض فتح التذكرة المحادثة كاملةً. تُنشَر الردود بالترتيب، وتظهر الرسائل الجديدة من فريقنا دون إعادة تحميل الصفحة.

Support ticket thread showing the conversation between the customer and the Authagonal team with a reply box and file attachment control

سلسلة تذكرة بينك وبين فريق Authagonal

  • تُعرَض الرسائل المترابطة بينك وبين فريق Authagonal بترتيب زمني.
  • رُدّ ضمن السلسلة وأرفق ملفات لمشاركة السجلات أو لقطات الشاشة أو الإعدادات.
  • تتحدّث السلسلة مباشرةً، فيظهر رد فريقنا فور إرساله.
  • وإذا رددت على بريد الإشعار بدلاً من ذلك، تُدرَج رسالتك في السلسلة تلقائياً.

كيف تصلك الردود

يعمل موظفو Authagonal على التذاكر من جانب الإدارة. تُشعَر عبر البريد الإلكتروني كلما رد الفريق، فلا حاجة إلى إبقاء البوابة مفتوحة للبقاء على اطلاع بالمحادثة.

مكتب دعم لمستخدميك

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

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

تفعيله

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

الإعدادالوصف
تفعيل دعم العملاءالمفتاح الرئيسي. وعند إيقافه، تُخفى صفحات المستخدمين النهائيين وصندوق وارد المشغّلين لديك معًا، وتجيب واجهات API الخاصة بها بـ 404.
السماح بطلبات الزوّار غير المسجّلينيتيح لزائر غير مسجَّل الدخول فتح تذكرة، وهي حالة المستخدم المقفَل حسابه. ويحميه فحص للروبوتات، وتستمر المحادثة عبر البريد الإلكتروني مع رابط خاص، إذ لا يوجد حساب لتسجيل الدخول إليه.
إشعارات البريد الإلكترونيمن يتلقى رسالة بريد إلكتروني عند وصول تذكرة أو رد مستخدم: لا أحد، أو عناوين محددة، أو فريق الدعم بأكمله (المالكون والمسؤولون والدعم)، فلا يضطر أحد إلى الجلوس لمراقبة صندوق الوارد.
اللغة الافتراضية للعملاءاللغة المفترضة للمستخدم عندما لا نعرف لغته بالفعل، لتذاكره ورسائله البريدية. وتغلب دائمًا اللغة التي حفظها المستخدم بنفسه، وعند عدم تعيين أي لغة تكون الإنجليزية. ويوجد هذا الإعداد في تبويب <strong>عام</strong> ضمن الإعدادات.
عنوان URL لـ Webhook الدعمعنوان URL تُرسَل إليه أحداث التذاكر بطلب POST، لدفعها إلى أدواتك الخاصة.

غير متاح في الخطة المجانية

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

ما يراه مستخدموك

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

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

صندوق وارد المشغّلين

يجيب فريقك من دعم العملاء في القائمة الجانبية للبوابة. وهو مكان منفصل عن تذاكرك الخاصة معنا، ومتاح لدور tenant:support وما فوقه، فيمكنك منح موظف دعم صلاحية الوصول إلى المكتب دون منحه بقية البوابة.

الإجراءالوصف
الردانشر في السلسلة. يُرسَل إلى المستخدم بريد إلكتروني ويرى الرد مباشرةً إن كانت الصفحة مفتوحة لديه.
الإسنادأسنِد التذكرة إلى عضو محدد في فريقك، حتى لا يجيب شخصان على التذكرة نفسها.
الحالة والأولويةانقل التذكرة بين مفتوحة وقيد الانتظار ومحلولة ومغلقة، وحدّد درجة إلحاحها. وتُحذف التذاكر المغلقة بعد مدة احتفاظ بدلًا من الاحتفاظ بها إلى الأبد.
الملاحظات الداخليةملاحظات مرئية لفريقك وحده، ولا تظهر للمستخدم أبدًا. وتُسجَّل التعديلات وعمليات الحذف في سجل التدقيق.
الفتح نيابةً عن مستخدمابدأ سلسلة مع أحد مستخدميك باختياره من دليلك، وذلك حين تكون المحادثة قد بدأت في مكان آخر.
التصعيد إلى Authagonalإذا تبيّن أن التذكرة تخص Authagonal لا منتجك، فصعّدها. عندئذٍ تُفتَح تذكرة مرتبطة لدى فريقنا، تحمل السلسلة حتى تلك اللحظة إن أردت، وتُربَط الاثنتان لتتابعهما معًا. ولا يمكن تصعيد التذكرة إلا مرة واحدة.

يكتب المستخدمون بلغتهم

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

المناطق الزمنية

تسجّل التذكرة المنطقة الزمنية التي فتحها المستخدم منها. وعندئذٍ تعرض كل رسالة توقيته المحلي بجوار توقيتك، فيُقرأ ردٌّ في الساعة 14:32 على أنه الساعة 02:32 التي كانها فعلًا لدى من ينتظره. ولا يُعرض شيء حين تكون المنطقة الزمنية مجهولة، كتذكرة وصلت عبر البريد الإلكتروني، أو حين تطابق منطقتك.

خطافات الويب

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

الحدثالوصف
support.ticket.createdفتح مستخدم تذكرة.
support.ticket.messageنُشرت رسالة في سلسلة، من مستخدم أو من أحد المشغّلين لديك. ويخبرك الحقل fromStaff في الحمولة بأيّهما.
support.ticket.status_changedتغيّرت حالة تذكرة، على سبيل المثال إلى «محلولة».
support.ticket.assignedأُسنِدت تذكرة إلى عضو في الفريق.

الاستيراد والترحيل

رحّل نظام هوية قائماً إلى مستأجر Authagonal الخاص بك. يُدعم مصدران، Duende IdentityServer (قاعدة بيانات SQL Server) وAuth0 (Management API). ويُجري كلٌّ منهما معاينة للقراءة فقط لتراجع بدقة ما الذي سيُنسخ قبل الالتزام.

الاستيراد من Duende IdentityServer

رحّل العملاء والنطاقات والمستخدمين والأدوار من قاعدة بيانات SQL Server قائمة لـ Duende IdentityServer إلى مستأجر Authagonal الخاص بك. يُجرى الاستيراد على مرحلتين، المعاينة ثم الالتزام، بحيث يمكنك مراجعة ما سيُنسخ قبل إجراء أي تغييرات.

ما الذي يُستورد

يقرأ أداة الاستيراد من جدول ConfigurationDb الخاص بـ Duende ومن جداول ASP.NET Identity، ويكتب الصفوف المُطابَقة في مستأجرك. أما العناصر قصيرة العمر مثل المنح المُخزّنة ورموز الأجهزة ومفاتيح التوقيع فيُتجاوز عنها.

الكيانالجداول المصدرملاحظات
العملاءClients, ClientSecrets, ClientGrantTypes, ClientScopes, ClientRedirectUrisتُستورد العملاء المعطّلون بحالة معطّلة. ويُتجاوز عن الأسرار المنتهية الصلاحية.
النطاقاتApiScopes, ApiResources, IdentityResourcesتُحفظ تعيينات مطالبات المستخدم حيثما أمكن التعرّف عليها.
المستخدمونAspNetUsers, AspNetUserClaimsتُنسخ تجزئات كلمات المرور (ASP.NET Identity V3) كما هي وتُعاد تجزئتها عند أول تسجيل دخول.
الأدوارAspNetRoles, AspNetUserRolesتُحفظ إسنادات الأدوار.
تسجيلات الدخول الخارجيةAspNetUserLoginsتُخزَّن للرجوع إليها؛ أعد ربط موفّري الهوية الأصليين عبر SSO بعد الاستيراد.

المعاينة قبل الالتزام

الصق سلسلة اتصال ConfigurationDb / IdentityDb الخاصة بـ Duende ثم انقر تشغيل المعاينة. تفتح المعاينة اتصالاً للقراءة فقط وتُحصي كل صف سيُستورَد. ولا تحدث أي عمليات كتابة.

  • أعداد الكيانات للعملاء والنطاقات والمستخدمين والأدوار وإسنادات الأدوار.
  • تحذيرات التعارض عندما يحتوي المستأجر الهدف بالفعل على عملاء (يُكتب فوق العملاء ذوي ClientIds المطابقة)، أو أدوار، أو نطاقات (يُتجاوز عن ذات الأسماء المطابقة).
  • تحذيرات حول الجداول غير المعروفة والأعمدة غير المُطابَقة لتعرف ما الذي سيُسقَط.
Import preview panel showing entity counts and warnings before committing the import

لوحة المعاينة مع الأعداد والتحذيرات

تجزئات كلمات المرور

يخزّن Duende كلمات المرور باستخدام ASP.NET Identity V3 (PBKDF2). يتحقق PasswordHasher الخاص بـ Authagonal من هذا التنسيق مباشرةً ويعيد تجزئته إلى التنسيق الأصلي عند أول تسجيل دخول ناجح، فيحتفظ المستخدمون بكلمات مرورهم الحالية دون الحاجة إلى عملية إعادة تعيين.

التوفيق بين معرّفات المستخدمين

إذا كان لدى مستخدم موجود بالفعل في هذا المستأجر نفس البريد الإلكتروني لسجلّ وارد، فإن الاستيراد يُدوّر قيمة userId الخاصة بذلك الحساب إلى sub المصدر قبل الاستيراد، بحيث تُرفَق الأدوار وعمليات تسجيل الدخول والمطالبات المستوردة بالحساب الموجود، وتستمر التطبيقات التي تشير إلى المستخدم بالفعل عبر sub المصدر الخاص به في العمل بعد التحويل. تُحفَظ كلمة المرور والملف الشخصي الحاليان للحساب؛ وتُدمج أدوار المصدر فوقها. تسرد المعاينة كل حساب سيجري التوفيق بشأنه قبل الالتزام.

تشغيل الاستيراد

انقر بدء الاستيراد بعد مراجعة المعاينة. تكتب مرحلة الالتزام العملاء والنطاقات والمستخدمين والأدوار ومراجع تسجيلات الدخول الخارجية في مخازن مستأجرك. ويُكتب فوق العملاء ذوي clientId المطابق، بينما يُتجاوز عن الصفوف ذات scope name أو email أو role name المطابق، فأداة الاستيراد آمنة لإعادة التشغيل.

ما الذي لا يُستورد

  • المنح المُخزّنة ورموز الأجهزة والجلسات على جانب الخادم، عناصر قصيرة العمر تُعاد إنشاؤها تلقائياً.
  • مفاتيح التوقيع، يُصدر Authagonal مفاتيحه الخاصة لكل مستأجر.
  • الأعمدة والجداول المخصصة، أي شيء خارج المخطط القياسي لـ Duende يظهر كتحذير لتعرف أن البيانات قد أُسقطت.
  • العملاء المعطّلون، يُستوردون بحالة معطّلة؛ أعد تفعيلهم من صفحة العملاء عند الاستعداد.

غير متاح في بيئة الاختبار

يُجرى الاستيراد على المستأجر المباشر فقط. اخرج من وضع بيئة الاختبار قبل الاستيراد.

الاستيراد من Auth0

اربط Authagonal بـ Management API الخاص بمستأجر Auth0 لديك وانقل تطبيقاتك وواجهات API والأدوار والمستخدمين واتصالات المؤسسات. تُحفظ معرّفات المستخدمين والتطبيقات المستوردة، فتظل مراجع sub وclient_id الحالية قابلة للحلّ بعد التحويل.

ما الذي ستحتاج إليه

أنشئ تطبيق Machine-to-Machine في Auth0 مصرّحاً له باستخدام Management API، مع منحه نطاقات القراءة هذه: read:users، read:clients، read:resource_servers، read:roles، read:connections، read:client_grants. الصق نطاقه ومعرّف العميل وسرّ العميل في نموذج الاستيراد، فهي تُستخدم للاستيراد فقط.

ما الذي يُستورد

الكيانالجداول المصدرملاحظات
التطبيقاتclients, client-grantsيُكتشف نوع العميل (عام أم سرّي) تلقائياً. وتُعاد تجزئة أسرار العملاء كي تستمر في العمل.
واجهات API والنطاقاتresource-serversتُسنَد الجماهير (audiences) والنطاقات إلى كل عميل انطلاقاً من منحه.
الأدوارroles + assignmentsتُحفظ إسنادات الأدوار لكل مستخدم.
المستخدمونusers + identitiesتُنقل الملفات الشخصية والبيانات الوصفية؛ وتصبح الهويات الاجتماعية والمؤسسية تسجيلات دخول مرتبطة.
الاتصالاتconnections (OIDC)تصبح اتصالات OIDC المؤسسية موفّرين فيدراليين. أما اتصالات SAML والاجتماعية وقواعد البيانات فيُتجاوز عنها مع تحذير.

كلمات المرور

لا يُعيد Management API الخاص بـ Auth0 تجزئات كلمات المرور أبداً. إذا كان لديك تصدير كلمات المرور المجمّع المدعوم من فريق Auth0 (NDJSON)، فقدّمه، إذ تُستورد تجزئات bcrypt كما هي ويحتفظ مستخدموك بكلمات مرورهم دون إعادة تعيين. كما يحمل ذلك الملف مجموعة مستخدميك الكاملة، متجاوزاً حدّ سرد 1000 مستخدم في واجهة API لدى Auth0. وبدونه، يُستورد المستخدمون كملفات شخصية ويضبطون كلمة مرور جديدة عند أول تسجيل دخول.

المعاينة والتدوير والحدود نفسها

المعاينة وتدوير userId للمالك والالتزام القابل لإعادة التشغيل وقيد بيئة الاختبار الموضّحة أعلاه تنطبق على عمليات استيراد Auth0 أيضاً.

مرجع API

يوفّر كل مستأجر خادم OIDC متوافقًا مع المعايير على https://{slug}.authagonal.io. تتبع جميع نقاط النهاية مواصفات OAuth 2.0 وOpenID Connect. يغطّي هذا المرجع كل نقطة نهاية قد يحتاج تطبيقك إلى التفاعل معها.

OIDC Authorization Code Flow with PKCE: sequence diagram showing the 9-step flow between your app, the browser, and Authagonal

تدفّق رمز التفويض مع PKCE

اكتشاف OIDC وJWKS

يتيح مستند الاكتشاف لمكتبات عميل OIDC ضبط نفسها تلقائيًا. لا حاجة إلى أي مصادقة لأيٍّ من نقطتي النهاية.

GET /.well-known/openid-configuration

تُعيد مستند تكوين موفّر OpenID. تتضمّن الاستجابة كل البيانات الوصفية التي يحتاجها عميلك للتفاعل مع هذا المستأجر.

الحقلالوصف
issuerعنوان URL لمُصدِر المستأجر
authorization_endpointعنوان URL لطلبات التفويض
token_endpointعنوان URL لتبادل الرموز
userinfo_endpointعنوان URL لجلب مطالبات المستخدم
jwks_uriعنوان URL لمجموعة مفاتيح الويب JSON
revocation_endpointعنوان URL لإبطال الرموز
introspection_endpointعنوان URL لفحص الرموز
end_session_endpointعنوان URL لتسجيل الخروج / إنهاء الجلسة
device_authorization_endpointعنوان URL لطلبات تفويض الأجهزة
pushed_authorization_request_endpointعنوان URL لنقطة نهاية طلب التفويض المدفوع (PAR) (RFC 9126).
require_pushed_authorization_requestsما إذا كان المستأجر يتطلّب PAR على نطاق عام. حتى عندما تكون هذه القيمة false، لا يزال بإمكان العملاء الأفراد ضبط RequirePushedAuthorizationRequests = true.
scopes_supportedقائمة النطاقات المدعومة
response_types_supportedأنواع الاستجابة المدعومة
grant_types_supportedأنواع المنح المدعومة
code_challenge_methods_supportedأساليب PKCE المدعومة (S256)
backchannel_logout_supportedما إذا كان تسجيل الخروج عبر القناة الخلفية مدعومًا

GET /.well-known/openid-configuration/jwks

تُعيد مجموعة مفاتيح الويب JSON المستخدَمة للتحقق من تواقيع الرموز. تحتوي الاستجابة على مصفوفة keys تضم مفاتيح EC P-256 العامة (تُوقَّع الرموز بـ ES256)، يتضمّن كل منها الحقول kty (EC) وuse وkid وalg وcrv وx وy.

Fetch discovery document
curl https://acme.authagonal.io/.well-known/openid-configuration

نقطة نهاية التفويض

GET /connect/authorize

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

المعاملمطلوبالوصف
response_typeنعميجب أن يكون "code"
client_idنعممُعرّف العميل المسجّل الخاص بك
redirect_uriنعميجب أن يطابق تمامًا عنوان إعادة توجيه URI مسجّلًا
scopeنعمقائمة بالنطاقات مفصولة بمسافات (مثل "openid profile email")
stateموصى بهقيمة مبهمة لحماية CSRF، تُعاد دون تغيير في إعادة التوجيه
code_challengeمطلوب في حال استخدام PKCEتجزئة SHA-256 المُرمّزة بترميز Base64url لقيمة code_verifier
code_challenge_methodمطلوب في حال استخدام PKCEيجب أن يكون "S256"
nonceاختياريقيمة مرتبطة برمز الهوية للحماية من إعادة التشغيل
login_hintاختياريملء حقل البريد الإلكتروني مسبقًا في صفحة تسجيل الدخول

استجابة النجاح: إعادة توجيه 302 إلى redirect_uri مع معاملي الاستعلام code وstate.

استجابة الخطأ: إعادة توجيه 302 مع معاملات الاستعلام error وerror_description وstate.

PKCE مطلوب

إن PKCE مطلوب افتراضيًا لجميع العملاء. أنشئ قيمة code_verifier (سلسلة عشوائية من 43 حرفًا أو أكثر)، وجزّئها باستخدام SHA-256، ثم رمّز النتيجة بترميز Base64url لإنشاء قيمة code_challenge.

طلبات التفويض المدفوعة (PAR)

RFC 9126. بدلًا من وضع كل معاملات التفويض على عنوان URL، يرسل عميلك طلب POST بها إلى /connect/par مع مصادقة العميل المعتادة ويستردّ قيمة request_uri مبهمة قصيرة العمر. ثم يزور المتصفّح /connect/authorize?client_id=...&request_uri=...، فلا يصل أي شيء آخر إلى سجل المتصفّح أو سجلات الخادم أو ترويسات Referer، ويكون الخادم قد تحقّق بالفعل من سلامة المعاملات تحت مصادقة العميل.

POST /connect/par

مصادقة العميل هي نفسها المستخدَمة في /connect/token: مصادقة HTTP الأساسية باستخدام client_id/client_secret، أو بيانات اعتماد مُرمّزة في النموذج. ينشر العملاء العامون دون كلمة سر. يحمل النص نفس المعاملات التي ترسلها عادةً إلى /connect/authorize؛ أما request_uri نفسها فمرفوضة (تسلسل PAR محظور بموجب §2.1 من المواصفة). تُعيد 201 Created.

المعاملمطلوبالوصف
client_idنعممُعرّف العميل الخاص بك. يجب أن يطابق العميل المُصادَق عليه.
client_secretالعملاء السرّيونكلمة سر العميل الخاصة بك. مطلوبة للعملاء السرّيين.
response_typeنعميجب أن يكون "code"
redirect_uriنعميجب أن يطابق تمامًا عنوان إعادة توجيه URI مسجّلًا
scopeنعمقائمة بالنطاقات مفصولة بمسافات (مثل "openid profile email")
code_challengeمطلوب في حال استخدام PKCEتجزئة SHA-256 المُرمّزة بترميز Base64url لقيمة code_verifier
code_challenge_methodمطلوب في حال استخدام PKCEيجب أن يكون "S256"
stateموصى بهقيمة مبهمة لحماية CSRF، تُعاد دون تغيير في إعادة التوجيه
nonceاختياريقيمة مرتبطة برمز الهوية للحماية من إعادة التشغيل

الاستجابة

الحقلالوصف
request_uriمرجع مبهم يُستخدَم لمرة واحدة، مثل <code>urn:ietf:params:oauth:request_uri:abc123…</code>. مرّره إلى <code>/connect/authorize</code> بصفته <code>request_uri</code>.
expires_inعمر قيمة <code>request_uri</code> بالثواني. القيمة الافتراضية هي 90، وهي قيمة نموذجية لموفّري الهوية المرجعيين.

في طلب المتابعة GET /connect/authorize?client_id=…&request_uri=…، تُسحَب جميع المعاملات الأخرى من الحمولة المدفوعة ويُتجاهَل أي معاملات استعلام إضافية. يجب أن يطابق client_id في استدعاء التفويض العميل الذي دفع الطلب. وبمجرد استهلاك قيمة request_uri (أو انقضاء expires_in)، تُزال من المخزن.

فرض PAR لكل عميل

فعّل خيار طلب طلبات التفويض المدفوعة على عميل (البوابة، العملاء، افتح العميل، تبويب الأمان) لرفض استدعاءات /connect/authorize العادية منه. يجمع الوضع الموصى به للعملاء عالي المخاطر بين RequirePushedAuthorizationRequests = true وPKCE، وهو ما يزيل شريط عناوين URL بصفته سطح هجوم بالكامل.
Push an authorization request and follow up
# 1. Push parameters (server returns request_uri + expires_in)
curl -X POST https://acme.authagonal.io/connect/par \
  -u "my-app:CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "response_type=code" \
  -d "redirect_uri=https://app.example.com/callback" \
  -d "scope=openid profile email" \
  -d "state=$(openssl rand -hex 16)" \
  -d "code_challenge=YOUR_CODE_CHALLENGE" \
  -d "code_challenge_method=S256"

# 2. Send the user to /authorize with only client_id + request_uri
# https://acme.authagonal.io/connect/authorize?client_id=my-app&request_uri=urn:ietf:params:oauth:request_uri:abc123...

نقطة نهاية الرموز

POST /connect/token

تبادل بيانات الاعتماد بالرموز. يجب أن تستخدم الطلبات Content-Type: application/x-www-form-urlencoded. يمكن توفير مصادقة العميل عبر مصادقة HTTP الأساسية (Authorization: Basic base64(client_id:client_secret)) أو بصفتها معاملات في نص النموذج (client_id + client_secret).

منح رمز التفويض

المعاملمطلوبالوصف
grant_typeنعم"authorization_code"
codeنعمرمز التفويض المأخوذ من إعادة التوجيه
redirect_uriنعميجب أن يطابق عنوان URI المستخدَم في طلب التفويض
code_verifierمطلوب في حال استخدام PKCEالسلسلة العشوائية الأصلية المستخدَمة لإنشاء code_challenge
client_idنعممُعرّف العميل الخاص بك (إن لم تكن تستخدم مصادقة Basic)
client_secretالعملاء السرّيونكلمة سر العميل الخاصة بك (إن لم تكن تستخدم مصادقة Basic)

منح رمز التحديث

المعاملمطلوبالوصف
grant_typeنعم"refresh_token"
refresh_tokenنعمرمز التحديث المراد تبادله
client_idنعممُعرّف العميل الخاص بك
client_secretالعملاء السرّيونكلمة سر العميل الخاصة بك

منح بيانات اعتماد العميل

المعاملمطلوبالوصف
grant_typeنعم"client_credentials"
client_idنعممُعرّف العميل الخاص بك
client_secretنعمكلمة سر العميل الخاصة بك
scopeاختياريالنطاقات المطلوبة مفصولة بمسافات

منح رمز الجهاز

المعاملمطلوبالوصف
grant_typeنعم"urn:ietf:params:oauth:grant-type:device_code"
device_codeنعمرمز الجهاز المأخوذ من استجابة تفويض الجهاز
client_idنعممُعرّف العميل الخاص بك
client_secretالعملاء السرّيونكلمة سر العميل الخاصة بك

استجابة الرمز:

الحقلالوصف
access_tokenرمز الوصول لاستدعاءات API
token_type"Bearer"
expires_inعمر الرمز بالثواني
id_tokenرمز هوية OpenID Connect (عند طلب نطاق openid)
refresh_tokenرمز التحديث (عند منح نطاق offline_access)
Exchange authorization code with PKCE
curl -X POST https://acme.authagonal.io/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTHORIZATION_CODE" \
  -d "redirect_uri=https://app.example.com/callback" \
  -d "client_id=my-app" \
  -d "code_verifier=YOUR_CODE_VERIFIER"

نقطة نهاية UserInfo

GET /connect/userinfo

تُعيد مطالبات حول المستخدم المُصادَق عليه. تتطلّب رمز وصول صالحًا يحمل نطاق openid.

الحقلالنوعالوصف
substringمُعرّف المستخدم الفريد
emailstringعنوان البريد الإلكتروني للمستخدم
email_verifiedbooleanما إذا كان البريد الإلكتروني قد تم التحقق منه
given_namestringالاسم الأول
family_namestringاسم العائلة
namestringالاسم الكامل المعروض
phone_numberstringرقم الهاتف (إن تم توفيره). يُصدَر ضمن النطاق <code>phone</code>.
org_idstringالمؤسسة التي ينتمي إليها المستخدم. يخصّصها تطبيق التزويد الخاص بك (انظر تطبيقات التزويد) أو تُضبط عبر PUT /api/v1/users/{userId}؛ ولا يشتقّها Authagonal أبدًا. تُصدر ضمن نطاق profile، وتغيب عندما لا تكون للمستخدم مؤسسة.
rolesstring[]مصفوفة الأدوار المُسنَدة. لا تُصدَر إلا عندما يحمل الرمز النطاق <code>roles</code>.
groupsobject[]مصفوفة عضويات المجموعات، يحمل كل عنصر منها مُعرّفًا واسمًا. لا تُصدَر إلا عندما يحمل الرمز النطاق <code>groups</code>.
Fetch user info
curl https://acme.authagonal.io/connect/userinfo \
  -H "Authorization: Bearer ACCESS_TOKEN"

فحص الرموز (RFC 7662)

POST /connect/introspect

يتحقّق من رمز ويعيد بياناته الوصفية. يتطلّب بيانات اعتماد العميل (مصادقة Basic أو معاملات في نص النموذج).

المعاملمطلوبالوصف
tokenنعمالرمز المراد فحصه
token_type_hintاختياريتلميح حول نوع الرمز (مثل "refresh_token")

استجابة الرمز النشط:

الحقلالوصف
activetrue
subالموضوع (مُعرّف المستخدم)
client_idالعميل الذي أُصدِر له الرمز
scopeالنطاقات الممنوحة مفصولة بمسافات
issالمُصدِر
expوقت انتهاء الصلاحية (طابع زمني Unix)
iatوقت الإصدار (طابع زمني Unix)
audالجمهور
token_typeنوع الرمز (مثل "Bearer")

استجابة الرمز غير النشط: { "active": false }

دائمًا 200 OK

وفقًا لـ RFC 7662، تُجيب نقطة نهاية الفحص بـ 200 OK لأي رمز، فلا يمكن استخدامها لتعداد الرموز. فالرمز غير الصالح أو منتهي الصلاحية أو المُبطَل يُعيد ببساطة active: false. والاستثناء الوحيد هو المستدعي نفسه: العميل الذي يفشل في المصادقة يحصل على 401 invalid_client.
Introspect a token
curl -X POST https://acme.authagonal.io/connect/introspect \
  -u "my-app:CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=ACCESS_OR_REFRESH_TOKEN"

إبطال الرموز (RFC 7009)

POST /connect/revocation

يُبطل رمزًا أُصدِر مسبقًا. يتطلّب بيانات اعتماد العميل.

المعاملمطلوبالوصف
tokenنعمالرمز المراد إبطاله
token_type_hintاختياريتلميح حول نوع الرمز (مثل "refresh_token")

تُعيد نقطة النهاية دائمًا 200 OK، حتى للرموز غير الصالحة أو المُبطَلة بالفعل، وفقًا لمواصفة RFC 7009.

رموز الوصول والتحديث

يمكن إبطال رموز التحديث ورموز الوصول كلتيهما. وإبطال رمز تحديث يُبطل أيضًا رموز الوصول المُصدَرة منه. ويرفض الفحص (introspection) وuserinfo رمز الوصول المُبطَل، لكن خادم الموارد الذي يتحقق من JWT محليًا يظل يقبله حتى تنتهي صلاحيته، لذا اجعل أعمار رموز الوصول قصيرة.

تفويض الأجهزة (RFC 8628)

POST /connect/deviceauthorization

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

المعاملمطلوبالوصف
client_idنعممُعرّف العميل الخاص بك
client_secretالعملاء السرّيونكلمة سر العميل الخاصة بك
scopeاختياريالنطاقات مفصولة بمسافات (القيمة الافتراضية "openid")

الاستجابة:

الحقلالوصف
device_codeرمز التحقق من الجهاز (يُستخدَم للاستعلام المتكرّر)
user_codeالرمز المعروض للمستخدم بصيغة XXXX-XXXX
verification_uriعنوان URL الذي يزوره المستخدم لإدخال الرمز
verification_uri_completeعنوان URL مع ملء user_code مسبقًا
expires_in300 افتراضيًا (بالثواني، أي أن الرمز صالح لمدة 5 دقائق). يُضبط لكل عميل.
interval5 (بالثواني، الحد الأدنى لفترة الاستعلام المتكرّر)

تدفّق الموافقة: يزور المستخدم verification_uri، ويُدخل user_code، ويوافق على الطلب. وفي غضون ذلك، يستعلم الجهاز من نقطة نهاية الرموز باستخدام device_code.

رموز أخطاء الاستعلام المتكرّر:

الخطأالمعنى
authorization_pendingلم يوافق المستخدم بعد، تابع الاستعلام
expired_tokenانتهت صلاحية رمز الجهاز، أعد بدء التدفّق
access_deniedرفض المستخدم طلب التفويض
Request device authorization
curl -X POST https://acme.authagonal.io/connect/deviceauthorization \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=my-cli" \
  -d "scope=openid profile email"

إنهاء الجلسة / تسجيل الخروج

GET POST /connect/endsession

يسجّل خروج جلسة المستخدم الحالية، ويُخطر كل عميل لديه عنوان URI مسجّل لتسجيل الخروج عبر القناة الخلفية أو الأمامية، ويُبطل المنح المرتبطة بتلك الجلسة. وبدون id_token_hint يطابق الجلسة الحالية، يُطلب من المستخدم أولًا تأكيد تسجيل الخروج.

المعاملمطلوبالوصف
id_token_hintاختياريرمز الهوية، يُستخدَم للتحقق من post_logout_redirect_uri
post_logout_redirect_uriاختياريوجهة إعادة التوجيه بعد تسجيل الخروج (يجب أن تكون مسجّلة)
stateاختياريقيمة مبهمة تُعاد في إعادة التوجيه

إذا تم توفير قيمة post_logout_redirect_uri صالحة وطابقت عنوان URI مسجّلًا، فسيتلقّى المستخدم إعادة توجيه 302. وإلا فستؤكّد استجابة JSON أن الجلسة قد أُنهيت.

تسجيل الخروج عبر القناة الخلفية

عندما يسجّل مستخدم خروجه، يرسل Authagonal رمز JWT موقّعًا إلى BackChannelLogoutUri الخاص بكل عميل. يحتوي رمز JWT على sub وaud وiss ومطالبة الحدث http://schemas.openid.net/event/backchannel-logout. وينبغي لتطبيقك إبطال جلسة المستخدم المحلية عند تلقّي هذا الإشعار.

مرجع API لـ SCIM 2.0

يدعم Authagonal بروتوكول SCIM 2.0 لتزويد المستخدمين والمجموعات تلقائيًا. ويمكن لموفّري الهوية مثل Okta وAzure AD وOneLogin استخدام هذا الـ API للحفاظ على مزامنة مستأجر Authagonal الخاص بك مع دليل شركتك.

عنوان URL الأساسي: https://{slug}.authagonal.io/scim/v2

المصادقة: تتطلّب جميع الطلبات رمز Bearer. أنشئ رمز SCIM في البوابة في صفحة SCIM: اختر العميل الذي يزوّده موفّر الهوية لديك، ثم إنشاء رمز.

الترويسات الشائعة:

الترويسةالقيمة
AuthorizationBearer SCIM_TOKEN
Content-Typeapplication/scim+json

تقبل نقاط نهاية القوائم count (القيمة الافتراضية 100، والحد الأقصى 200، و0 يُعيد الإجمالي فقط) والتصفية عبر معامل filter (مثل userName eq "[email protected]"). تُقسَّم صفحات المستخدمين باستخدام cursor: مرّر nextCursor من الاستجابة السابقة. وتقبل المجموعات إما startIndex (يبدأ من 1) أو cursor.

المستخدمون

GET /scim/v2/Users: سرد المستخدمين مع تقسيم اختياري إلى صفحات وتصفية.

معامل الاستعلامالوصف
startIndexلا تُقبل للمستخدمين إلا القيمة 1، فاستخدم cursor للتقسيم إلى صفحات بدلًا من ذلك. والقيمة الأكبر تُعيد 400 invalidValue.
cursorمؤشر تقسيم صفحات معتم: مرّر nextCursor من الصفحة السابقة للحصول على الصفحة التالية
countالعدد الأقصى للنتائج في كل صفحة (القيمة الافتراضية: 100، الحد الأقصى: 200، و0 يُعيد الإجمالي فقط)
filterتعبير تصفية SCIM (مثل userName eq "[email protected]")

GET /scim/v2/Users/{id}: الحصول على مستخدم واحد عبر مُعرّف مستخدم Authagonal الخاص به.

POST /scim/v2/Users: إنشاء مستخدم جديد. تُعيد 201 Created.

الحقلمطلوبالوصف
userNameنعمعنوان البريد الإلكتروني (يجب أن يكون فريدًا داخل المستأجر)
name.givenNameلاالاسم الأول
name.familyNameلااسم العائلة
displayNameلاالاسم الكامل المعروض
activeلاما إذا كان المستخدم نشطًا (القيمة الافتراضية: true)
externalIdلاالمُعرّف من موفّر الهوية المنبع

PUT /scim/v2/Users/{id}: استبدال كامل لمورد المستخدم. يجب توفير جميع الحقول.

PATCH /scim/v2/Users/{id}: تحديث جزئي باستخدام SCIM PatchOp.

العمليةالمسارات المدعومةقيمة المثال
replaceuserName, active, name.givenName, name.familyName, displayName, externalId, preferredLanguagetrue / false، أو قيمة نصية
adduserName, active, name.givenName, name.familyName, displayName, externalId, preferredLanguagetrue / false، أو قيمة نصية
removename.givenName, name.familyName, displayName, externalId, preferredLanguage(لا حاجة إلى قيمة)

DELETE /scim/v2/Users/{id}: يحذف المستخدم حذفًا ناعمًا (يعطّل الحساب ويُبطل جميع الرموز). تُعيد 204 No Content.

Create a user via SCIM
curl -X POST https://acme.authagonal.io/scim/v2/Users \
  -H "Authorization: Bearer SCIM_TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "[email protected]",
    "name": {
      "givenName": "Jane",
      "familyName": "Smith"
    },
    "displayName": "Jane Smith",
    "active": true,
    "externalId": "ext-12345"
  }'

المجموعات

GET /scim/v2/Groups: سرد جميع المجموعات مع تقسيم اختياري إلى صفحات وتصفية.

GET /scim/v2/Groups/{id}: الحصول على مجموعة واحدة عبر المُعرّف، بما في ذلك قائمة أعضائها.

POST /scim/v2/Groups: إنشاء مجموعة جديدة. تُعيد 201 Created.

الحقلمطلوبالوصف
displayNameنعمالاسم المعروض للمجموعة
membersلامصفوفة من كائنات الأعضاء، يحمل كل منها حقل value يحتوي على مُعرّف المستخدم
externalIdلاالمُعرّف من موفّر الهوية المنبع

PUT /scim/v2/Groups/{id}: استبدال كامل لمورد المجموعة (بما في ذلك قائمة أعضائها).

PATCH /scim/v2/Groups/{id}: تحديث جزئي: إضافة أعضاء أو إزالتهم أو استبدالهم، أو تغيير displayName وexternalId.

DELETE /scim/v2/Groups/{id}: يحذف المجموعة حذفًا نهائيًا. تُعيد 204 No Content.

Add members to a group via PATCH
curl -X PATCH https://acme.authagonal.io/scim/v2/Groups/GROUP_ID \
  -H "Authorization: Bearer SCIM_TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [
      {
        "op": "add",
        "path": "members",
        "value": [
          { "value": "USER_ID_1" },
          { "value": "USER_ID_2" }
        ]
      }
    ]
  }'

استجابات أخطاء SCIM

عند فشل طلب SCIM، يتبع نص الاستجابة مخطط أخطاء SCIM: { "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"], "status": "400", "detail": "..." }. تشمل رموز الحالة الشائعة 400 (طلب غير صالح)، و404 (المورد غير موجود)، و409 (تعارض / تكرار)، و429 (تجاوز حد المعدل).

API البوابة (الأتمتة)

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

عنوان URL الأساسي: https://portal-api.<your-domain>/api/v1. تُصادَق الطلبات برمز وصول من نوع Bearer، ويُؤخذ المستأجر من الرمز لا من عنوان URL.

إنشاء بيانات اعتماد لـ API

في البوابة، افتح العملاء ← إنشاء بيانات اعتماد API، واختر مستوى وصول، وامنحها اسمًا. ينشئ Authagonal عميل OAuth من نوع client_credentials مهيأً للعمل مع API البوابة، ويعيد معرّف عميل وسرًّا.

انسخ السر فورًا

يُعرض سر العميل مرة واحدة فقط، مباشرة بعد الإنشاء. خزّنه في مدير الأسرار لديك قبل إغلاق النافذة، فإن فقدته، احذف بيانات الاعتماد وأنشئ غيرها.

مستويات الوصول

النطاقيمنح
tenant:ownerوصول كامل، بما في ذلك الإجراءات التدميرية الخاصة بالمالك وحده مثل حذف المستأجر بأكمله.
tenant:adminإدارة كل شيء باستثناء الإجراءات الخاصة بالمالك وحده، أي المستخدمين والعملاء وSSO والمجموعات والأدوار والعلامة التجارية والإعدادات.
tenant:developerإدارة العملاء والنطاقات والعلامة التجارية وتطبيقات التزويد.
tenant:supportقراءة المستخدمين وإدارتهم لأغراض مهام الدعم، وقراءة سجل التدقيق.

لا يمكنك منح أكثر مما تملك

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

الحصول على رمز

بادل بيانات الاعتماد برمز وصول عند نقطة نهاية الرمز الخاصة بمستأجرك، أي https://<your-tenant>.<your-domain>/connect/token، ثم أرسل الرمز كترويسة Bearer إلى API البوابة. تظل الرموز صالحة لمدة ساعة واحدة.

احصل على رمز، ثم استدعِ الـ API
# 1. Exchange the credential for an access token (your tenant's token endpoint)
curl -X POST https://acme.authagonal.io/connect/token \
  -d grant_type=client_credentials \
  -d client_id=api-3f2a... \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d scope=tenant:admin

# Response: { "access_token": "ey...", "token_type": "Bearer", "expires_in": 3600 }

# 2. Call the Portal API with the access token
curl https://portal-api.authagonal.io/api/v1/users \
  -H "Authorization: Bearer $ACCESS_TOKEN"

نقاط النهاية

جميع المسارات نسبية إلى عنوان URL الأساسي وتتطلب رمز وصول من نوع Bearer. النطاق المذكور بجانب كل مجموعة هو الحد الأدنى لمستوى وصول بيانات الاعتماد الذي تحتاجه. يختلف التقسيم إلى صفحات حسب المورد: المستخدمون وسجل التدقيق يقبلان count (من 1 إلى 200، والقيمة الافتراضية 50) وafter المضبوط على continuationToken من الاستجابة السابقة؛ والمجموعات تقبل startIndex وcount؛ والمنظمات تقبل limit وcursor؛ أما العملاء والأدوار والنطاقات فتُعيد كل الصفوف.

العملاءtenant:developer

GET/api/v1/clientsسرد عملاء OAuth.

GET/api/v1/clients/{id}الحصول على عميل واحد بمعرّفه.

POST/api/v1/clientsإنشاء عميل. يعيد 201 مع سجل العميل. لا تُعاد الأسرار هنا: أنشئ سرًّا عبر POST /api/v1/clients/{clientId}/secrets، الذي يعرضه مرة واحدة.

PUT/api/v1/clients/{id}تحديث عميل (عناوين إعادة التوجيه URIs، أنواع المنح، فترات صلاحية الرموز، متطلبات PKCE/PAR).

DELETE/api/v1/clients/{id}حذف عميل.

POST/api/v1/clients/api-credentialإصدار بيانات اعتماد API البوابة من آلة إلى آلة.

المستخدمونtenant:support

GET/api/v1/usersسرد المستخدمين. يدعم count و search (بادئة البريد الإلكتروني أو الاسم) و organizationId للتصفية على مؤسسة واحدة و after للترقيم بالمؤشر.

GET/api/v1/users/countإجمالي عدد المستخدمين للمستأجر.

GET/api/v1/users/stats/mfaإحصائيات تسجيل MFA.

GET/api/v1/users/{id}الحصول على مستخدم واحد.

POST/api/v1/users/inviteدعوة مستخدم عبر البريد الإلكتروني. يُنشئ حسابًا معلّقًا ويرسل بالبريد رابطًا يعيّن فيه المدعو كلمة مروره بنفسه. ويضيف organizationId وorganizationRoles الاختياريان أيضًا عضوية في منظمة.

PUT/api/v1/users/{id}تحديث مستخدم (الملف الشخصي، البريد الإلكتروني، isActive، emailConfirmed، organizationId). يتطلب تغيير البريد الإلكتروني أو emailConfirmed الدور tenant:admin.

DELETE/api/v1/users/{id}حذف مستخدم.

GET/api/v1/users/{id}/mfaGet a user's enrolled MFA methods.

DELETE/api/v1/users/{id}/mfaReset a user's MFA enrollment. Needs tenant:admin.

الأدوارtenant:admin

GET/api/v1/rolesسرد الأدوار.

POST/api/v1/rolesإنشاء دور.

DELETE/api/v1/roles/{id}حذف دور.

POST/api/v1/roles/assignتعيين دور لمستخدم.

POST/api/v1/roles/unassignإزالة دور من مستخدم.

المجموعاتtenant:admin

GET/api/v1/groupsسرد المجموعات.

GET/api/v1/groups/{id}الحصول على مجموعة مع أعضائها.

POST/api/v1/groupsإنشاء مجموعة.

POST/api/v1/groups/{id}/membersإضافة أعضاء إلى مجموعة.

DELETE/api/v1/groups/{groupId}/members/{userId}إزالة عضو من مجموعة.

DELETE/api/v1/groups/{id}حذف مجموعة.

GET/api/v1/group-role-mappingsسرد تعيينات المجموعات إلى الأدوار (الأدوار الممنوحة عند إصدار الرمز بحسب عضوية المجموعة).

النطاقاتtenant:developer

GET/api/v1/scopesسرد نطاقات API.

POST/api/v1/scopesإنشاء نطاق.

DELETE/api/v1/scopes/{name}حذف نطاق.

اتصالات SSOtenant:admin

GET/api/v1/saml/connectionsسرد اتصالات SAML.

POST/api/v1/saml/connectionsإنشاء اتصال SAML.

DELETE/api/v1/saml/connections/{id}حذف اتصال SAML.

GET/api/v1/oidc/connectionsسرد اتصالات OIDC.

POST/api/v1/oidc/connectionsإنشاء اتصال OIDC.

DELETE/api/v1/oidc/connections/{id}حذف اتصال OIDC.

GET/api/v1/sso/domainsسرد النطاقات الموجَّهة إلى اتصالات SSO (اكتشاف نطاق الهوية الأصلي).

العلامة التجاريةtenant:developer

GET/api/v1/brandingالحصول على العلامة التجارية للمستأجر (الألوان، الشعار، اللغات المدعومة).

PUT/api/v1/brandingتحديث العلامة التجارية للمستأجر.

الإعداداتtenant:admin

GET/api/v1/settingsالحصول على إعدادات المستأجر (خطافات الويب، التسجيل العام، سياسة الرموز).

PUT/api/v1/settingsتحديث إعدادات المستأجر.

POST/api/v1/settings/webhook-secret/regenerateتدوير سر توقيع خطاف الويب.

POST/api/v1/settings/test-emailإرسال بريد إلكتروني تجريبي باستخدام إعدادات البريد الإلكتروني الحالية.

النطاقات المخصصة والبريد الإلكترونيtenant:admin

GET/api/v1/custom-domainsسرد نطاقات تسجيل الدخول المخصصة وحالة التحقق منها.

POST/api/v1/custom-domainsإضافة نطاق مخصص.

POST/api/v1/custom-domains/{domain}/verifyتشغيل التحقق عبر DNS لنطاق مخصص.

DELETE/api/v1/custom-domains/{domain}إزالة نطاق مخصص.

GET/api/v1/email/domains/{domainId}جلب سجلات DNS لنطاق بريد إلكتروني للمُرسِل وحالة التحقق منه.

سجل التدقيقtenant:support

GET/api/v1/auditالاستعلام في سجل تدقيق المستأجر.

تزويد المستخدمين عبر SCIM

لتزويد المستخدمين والمجموعات بالجملة من موفّر هوية (Entra، Okta)، استخدم SCIM 2.0 API بدلًا من نقاط النهاية هذه.

مثال: دعوة مستخدم

POST /api/v1/users/invite
curl -X POST https://portal-api.authagonal.io/api/v1/users/invite \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "firstName": "Ada",
    "lastName": "Lovelace"
  }'

# 200 OK
# { "userId": "8f3a...", "email": "[email protected]" }

كل ما تستطيع الواجهة فعله

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

API المنظمات

تتطلب كل المسارات أدناه سياسة TenantAdmin وتقع تحت /api/v1/organizations ما لم يُذكر خلاف ذلك. راجع API البوابة لمعرفة كيفية إصدار بيانات اعتماد. مساران للقوائم مقسّمان بمؤشر: مرّر limit (الافتراضي 50، من 1 إلى 200) وnextCursor السابق كـ cursor؛ وتعيد { items, nextCursor }، والمؤشر الخاطئ هو 400 invalid_cursor. ويحمل كائن المنظمة قائمة domains للقراءة فقط.

الطريقةالمسارالجسمملاحظات
GET/api/v1/organizations–صفحة واحدة من المنظمات بترتيب المعرّف. الاستعلام: cursor?، limit? (الافتراضي 50، من 1 إلى 200). تعيد { items, nextCursor }؛ وقيمة nextCursor الفارغة تعني الصفحة الأخيرة.
POST/api/v1/organizationsslug, name, brandingJson?, enabled?, requireMembershipForTokens?, allowAutoMembership?, metadata?201 + المنظمة. 409 slug_taken.
GET/api/v1/organizations/{idOrSlug}–يُبحث بالمعرّف أولًا ثم بالـ slug.
PUT/api/v1/organizations/{id}name?, brandingJson?, slug?, enabled?, requireMembershipForTokens?, allowAutoMembership?, metadata?تتغير الحقول المسماة فقط. ويُرفض slug مختلف: فهو ثابت بعد الإنشاء. ولا يمكن تغيير domains هنا.
DELETE/api/v1/organizations/{id}–يحذف أولًا كل عضويات المنظمة، ثم المنظمة نفسها.
GET/api/v1/organizations/{id}/members–صفحة واحدة من العضويات بترتيب معرّف المستخدم، مع البريد الإلكتروني/الاسم الحيّين للعضو المأخوذين من مخزن المستخدمين. الاستعلام: cursor?، limit?.
POST/api/v1/organizations/{id}/membersuserId? | email?, status?, roles?201 + العضوية. 404 user_not_found. 409 membership_exists. أدوار tenant:* وplatform:* المحجوزة تُرفض بـ 400 invalid_role ولا تُحذف بصمت.
PUT/api/v1/organizations/{id}/members/{userId}status?, roles?ضبط الحالة على active يختم joinedAt إن لم يكن مضبوطًا أصلًا.
DELETE/api/v1/organizations/{id}/members/{userId}–يزيل الصف نهائيًا، وليس تغييرًا للحالة.
POST/api/v1/organizations/{id}/domainsdomainيطالب بنطاق بريد إلكتروني، غير موثَّق. 201 + { domain, verified, verifiedAt, createdAt, recordName, recordValue }. 400 domain_invalid. 409 domain_exists, domain_taken.
POST/api/v1/organizations/{id}/domains/{domain}/verify–يبحث عن سجل TXT عند recordName ويطابق recordValue تمامًا. 200 + النطاق عند التوثيق (والتكرار 200 بلا أثر)؛ 409 verification_failed عند عدم التطابق؛ 409 domain_taken؛ 404 domain_not_found.
DELETE/api/v1/organizations/{id}/domains/{domain}–204. يُسقط المطالبة، موثَّقة كانت أم لا. يبقى الأعضاء الحاليون. 404 domain_not_found.
POST/api/v1/organizations/backfilldryRun? = trueيرحّل وسم AuthUser.organizationId القديم إلى صفوف Organization/OrganizationMembership حقيقية.
GET/api/v1/users/{userId}/organizations–كل منظمة ينتمي إليها هذا المستخدم، مع حالته وأدواره في كل منها.

شاشات تسجيل الدخول

هذه هي الشاشات المستضافة التي يراها المستخدمون النهائيون على خادم المصادقة الخاص بمستأجرك. يوفّر Authagonal كل شاشة جاهزة للاستخدام، فتحصل على تجربة تسجيل دخول كاملة وآمنة دون بناء أي واجهة. تستعرض هذه الصفحة كل شاشة وتبيّن أي إعدادات البوابة تتحكم بها.

علامة بيضاء بالكامل

كل شاشة هنا تُرسَم وفق إعدادات العلامة التجارية لمستأجرك، أي شعارك ولونك واسم تطبيقك وCSS المخصص. كما تحترم الشاشات prefers-color-scheme، فتنتقل بين الوضعين الفاتح والداكن لتطابق جهاز المستخدم.

تسجيل الدخول

Hosted sign-in screen with an email field, Continue button, single sign-on provider buttons, and forgot-password and create-account links
  • تدفق من خطوتين يبدأ بالبريد الإلكتروني: يُدخل المستخدم بريده الإلكتروني وينقر متابعة، ثم يظهر حقل كلمة المرور.
  • تظهر أزرار الدخول الموحّد "المتابعة باستخدام {provider}" تلقائيًا عند وجود اتصالات SSO.
  • روابط نسيت كلمة المرور وإنشاء حساب، ويمكن إظهار كلٍّ منها أو إخفاؤه.
  • اختبار Cloudflare Turnstile اختياري لردع محاولات تسجيل الدخول الآلية.

يُتحكم بها من إدارة البوابة

  • تضبط العلامة التجارية الشعار واللون واسم التطبيق والبريد الإلكتروني للدعم وCSS المخصص.
  • إظهار أو إخفاء رابطي نسيت كلمة المرور والتسجيل (العلامة التجارية).
  • تضيف اتصالات SSO أزرار الدخول الاجتماعي (صفحة SSO).
  • مدة الجلسة وعتبات القفل (الإعدادات → الجلسة).

التسجيل

Account registration screen with first and last name fields, email, password, and a live password-policy checklist
  • يجمع الاسم الأول والأخير (اختياري) والبريد الإلكتروني وكلمة المرور.
  • قائمة تحقق حيّة لسياسة كلمة المرور تتحدث أثناء كتابة المستخدم، فتتضح المتطلبات قبل الإرسال.
  • اختبار Cloudflare Turnstile اختياري.
  • رابط "تسجيل الدخول" للمستخدمين الذين لديهم حساب بالفعل.

يُتحكم بها من إدارة البوابة

  • إظهار أو إخفاء رابط التسجيل (العلامة التجارية). ولإيقاف التسجيل كليًا، أوقف السماح بالتسجيل العام (الإعدادات → الجلسة).
  • تتحكم سياسة كلمة المرور الخاصة بمستأجرك في قائمة التحقق.
  • تنسّق العلامة التجارية الشاشة بأكملها.

نسيت كلمة المرور

Forgot-password screen with an email field and a neutral check-your-email confirmation state
  • يُدخل المستخدم بريده الإلكتروني، ثم يرى تأكيدًا محايدًا بصيغة "تحقق من بريدك الإلكتروني".
  • الشاشة لا تكشف أبدًا ما إذا كان الحساب موجودًا، ما يحبط محاولات استكشاف الحسابات.
  • رابط "العودة إلى تسجيل الدخول" يعيد المستخدم إلى شاشة تسجيل الدخول.

يُتحكم بها من إدارة البوابة

  • إظهار أو إخفاء رابط نسيت كلمة المرور (العلامة التجارية).
  • يرسل توصيل البريد الإلكتروني الخاص بمستأجرك رسالة إعادة التعيين.
  • تنسّق العلامة التجارية الشاشة بأكملها.

إعادة تعيين كلمة المرور

Reset-password screen with new and confirm password fields and a live per-rule requirement checklist
  • حقلا كلمة المرور الجديدة وتأكيد كلمة المرور مع قائمة تحقق حيّة لكل قاعدة من المتطلبات.
  • حالة واضحة لـ رابط غير صالح أو منتهي الصلاحية عندما لا يعود رمز إعادة التعيين صالحًا.
  • حالة نجاح تؤكد تغيير كلمة المرور.

يُتحكم بها من إدارة البوابة

  • تتحكم سياسة كلمة المرور الخاصة بمستأجرك في قائمة التحقق.
  • تنسّق العلامة التجارية الشاشة بأكملها.

تحدي MFA

MFA challenge screen with a method switcher, a six-digit authenticator code field, recovery-code entry, and a passkey button
  • مبدّل طرق بين تطبيق المصادقة ومفتاح المرور ورمز الاسترداد.
  • حقل TOTP من 6 أرقام يُرسَل تلقائيًا بمجرد إدخال جميع الأرقام.
  • إدخال رمز الاسترداد للمستخدمين الذين فقدوا الوصول إلى تطبيق المصادقة لديهم.
  • زر مفتاح المرور للتحقق المدعوم بالعتاد.

يُتحكم بها من إدارة البوابة

  • تُضبط سياسة MFA لكل تطبيق على حدة (العملاء → الأمان).
  • أي مستخدم لديه عامل مسجَّل يُطالَب به دائمًا، بصرف النظر عن السياسة.

إعداد MFA

MFA setup screen showing enrolled-method status, authenticator QR code and manual key, passkey enrolment, and recovery-code generation
  • يعرض حالة الطرق المسجَّلة ليعرف المستخدم ما هو مُعدّ بالفعل.
  • إعداد تطبيق المصادقة عبر رمز QR، مع مفتاح يدوي بديل، وخطوة تأكيد.
  • تسجيل مفتاح المرور للمصادقة المدعومة بالعتاد.
  • إنشاء رموز الاسترداد لاستعادة الحساب.
  • تخطٍّ اختياري عندما يكون MFA بالخدمة الذاتية لا إلزاميًا.

يُتحكم بها من إدارة البوابة

  • تُضبط سياسة MFA لكل تطبيق على حدة، ويفرض الخيار إلزامي الإعداد عند تسجيل الدخول (العملاء → الأمان).
  • تنسّق العلامة التجارية الشاشة بأكملها.

تفويض الجهاز

Device authorization screen with a centered user-code entry field, an Approve button, and an approved confirmation state
  • حقل إدخال رمز المستخدم موسَّط للرمز المعروض على الجهاز.
  • خطوة موافقة لتفويض الجهاز.
  • شاشة تسجيل دخول وسيطة عندما لا يكون المستخدم مصادَقًا بعد.
  • تأكيد موافقة بمجرد تفويض الجهاز.

يُتحكم بها من إدارة البوابة

  • فعّل منح رمز الجهاز على التطبيق (العملاء → النطاقات والمنح).
  • اضبط مدة صلاحية رمز الجهاز (العملاء → الرموز).
Consent screen showing the requesting application's logo and name, a per-scope permission list, and Allow and Deny buttons
  • تعرض شعار العميل واسمه الطالب.
  • قائمة لكل نطاق بعناوين ودّية وسهلة القراءة لكل إذن.
  • زرّا السماح والرفض لمنح الوصول أو رفضه.
  • تذييل تلميح الموافقة يشرح ما يعنيه القرار.

يُتحكم بها من إدارة البوابة

  • فعّل طلب الموافقة لكل تطبيق على حدة (العملاء → عام).
  • يأتي الشعار والاسم وعنوان URL من البيانات الوصفية الخاصة بالتطبيق نفسه.
  • ترسم العلامة التجارية بطاقة الموافقة.

التطبيقات المتصلة (المنح)

Connected apps screen listing the applications a user has authorized with their scopes and granted date, plus a revoke control
  • تسرد كل تطبيق فوّضه المستخدم، مع اسمه ونطاقاته وتاريخ المنح.
  • إلغاء وصول تطبيق ما، مع خطوة تأكيد قبل نفاذ الإجراء.
  • حالة فارغة ودّية عندما لا يكون المستخدم قد فوّض أي تطبيقات.

يُتحكم بها من إدارة البوابة

  • تُملأ القائمة بـ التطبيقات التي تتطلب الموافقة.
  • تنسّق العلامة التجارية الشاشة بأكملها.

الحساب

صفحة حساب مستضافة بالخدمة الذاتية على /login/account حيث يدير المستخدمون المسجَّلون ملفهم الشخصي ولغتهم المفضّلة، دون الحاجة إلى الوصول إلى البوابة.

Self-service account screen with editable profile fields and a preferred Language selector
  • تحرير الاسم الأول والأخير والشركة والهاتف، ويُعرض عنوان البريد الإلكتروني للقراءة فقط.
  • اختيار لغة مفضّلة من اللغات المدعومة، وتعاين الواجهة الاختيار فورًا وتحفظه عند الحفظ.
  • تتحكم اللغة المحفوظة في الواجهة المستضافة للمستخدم وفي لغة الرسائل البريدية الإجرائية التي يتلقاها.

يُتحكم بها من إدارة البوابة

  • تنسّق العلامة التجارية الشاشة بأكملها.
  • اللغة المفضّلة ذاتها قابلة للتحرير من قبل المسؤول في صفحة المستخدمون بالبوابة.

تدفقات المصادقة

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

تسجيل الدخول

POST /api/auth/login

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

نص الطلب:

Login request
{
  "email": "[email protected]",
  "password": "correct-horse-battery-staple"
}

استجابة النجاح:

الحقلالنوعالوصف
userIdstringمعرّف المستخدم الفريد
emailstringعنوان البريد الإلكتروني للمستخدم
namestringاسم العرض الكامل
mfaAvailablebooleanما إذا كان المستخدم قد سجّل طرق MFA

استجابة طلب MFA: عندما يكون المستخدم قد سجّل MFA، تتضمن الاستجابة mfaRequired: true إلى جانب challengeId ومصفوفة methods تسرد طرق MFA المتاحة.

استجابة طلب إعداد MFA: عندما تكون سياسة MFA الخاصة بالتطبيق «مطلوبة» ولكن المستخدم لم يسجّل بعد، تتضمن الاستجابة mfaSetupRequired: true مع setupToken لتدفق التسجيل.

استجابات الخطأ:

رمز الخطأحالة HTTPالوصف
invalid_credentials401البريد الإلكتروني أو كلمة المرور غير صحيحة
account_disabled403تم تعطيل الحساب من قبل مسؤول
email_not_confirmed403لم يتحقق المستخدم من عنوان بريده الإلكتروني
locked_out423الحساب مقفل مؤقتًا (يتضمن retryAfter بالثواني). لا يُعاد إلا عندما تكون كلمة المرور صحيحة، أما كلمة المرور الخاطئة أثناء القفل فتُعيد invalid_credentials
sso_required409نطاق البريد الإلكتروني مهيأ لـ SSO (يتضمن redirectUrl)
too_many_attempts429محاولات تسجيل دخول كثيرة جدًا من عنوان IP هذا أو لهذا البريد الإلكتروني، حاول مرة أخرى لاحقًا
captcha_failed400فشل تحدي Turnstile أو أنه مفقود (فقط عند تفعيل Turnstile)

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

قفل الحساب: بعد maxFailedAttempts من محاولات تسجيل الدخول الفاشلة المتتالية، يُقفل الحساب لمدة lockoutDurationMinutes. كلا القيمتين قابلتان للضبط في إعدادات المستأجر.

صفحة تسجيل الدخول المستضافة

تستدعي صفحة تسجيل الدخول المستضافة نقطة نهاية تسجيل الدخول عادةً، لا تطبيقك مباشرةً. استخدم تدفق رمز التفويض في OIDC لبدء المصادقة، فسيُعاد توجيه مستخدميك إلى صفحة تسجيل الدخول المستضافة تلقائيًا.

التسجيل

POST /api/auth/register

ينشئ حساب مستخدم جديدًا ويرسل بريد تحقق. وما دام خيار <strong>اشتراط بريد إلكتروني مُتحقَّق منه لتسجيل الدخول</strong> (الإعدادات &rarr; الجلسة) مفعّلًا، وهو الإعداد الافتراضي، يجب على المستخدم التحقق من بريده الإلكتروني قبل أن يتمكن من تسجيل الدخول.

نص الطلب:

Registration request
{
  "email": "[email protected]",
  "password": "a-strong-password-here",
  "firstName": "Jane",
  "lastName": "Smith"
}
الحقلمطلوبالوصف
emailنعمعنوان البريد الإلكتروني (يجب أن يكون فريدًا)
passwordنعميجب أن يستوفي سياسة كلمة المرور للمستأجر
firstNameلاالاسم الأول
lastNameلااسم العائلة

النجاح: 201 Created مع userId للحساب الجديد. التسجيل ببريد إلكتروني مستخدَم بالفعل يعيد 201 أيضًا: فنحن لا نكشف أبدًا ما إذا كان البريد الإلكتروني موجودًا (لمنع تعداد الحسابات)، وبدلًا من ذلك نُعلِم صاحب الحساب الحقيقي عبر البريد الإلكتروني.

استجابات الخطأ:

رمز الخطأحالة HTTPالوصف
weak_password400كلمة المرور لا تستوفي سياسة كلمة المرور للمستأجر
rate_limited429محاولات تسجيل كثيرة جدًا
provisioning_rejected422رفض خطاف ويب للتزويد عملية التسجيل
invalid_email400عنوان البريد الإلكتروني غير صالح
captcha_failed400فشل تحدي Turnstile أو أنه مفقود (فقط عند تفعيل Turnstile)
public_signup_disabled403التسجيل العام معطّل لهذا المستأجر (الإعدادات &rarr; الجلسة)

سياسة كلمة المرور

تحقق من متطلبات كلمة المرور للمستأجر قبل الإرسال عبر GET /api/auth/password-policy. يعيد هذا قائمة rules: الحد الأدنى للطول وفئات الأحرف المطلوبة.

إعادة تعيين كلمة المرور

POST /api/auth/forgot-password

يطلب بريد إعادة تعيين كلمة المرور. تعيد نقطة النهاية دائمًا استجابة نجاح بصرف النظر عن وجود البريد الإلكتروني من عدمه، لمنع تعداد البريد الإلكتروني.

Forgot password request
{
  "email": "[email protected]"
}

POST /api/auth/reset-password

يعيد تعيين كلمة مرور المستخدم باستخدام الرمز الوارد في رابط البريد الإلكتروني.

Reset password request
{
  "token": "RESET_TOKEN_FROM_EMAIL",
  "newPassword": "new-strong-password"
}

الآثار الجانبية لإعادة تعيين كلمة المرور بنجاح:

  • يُعاد ضبط عدّاد محاولات تسجيل الدخول الفاشلة إلى صفر
  • تُلغى جميع رموز التحديث الموجودة
  • يُنشأ ختم أمان جديد (ما يُبطل جميع الجلسات الموجودة)

إعداد MFA والتحقق منه

يدعم Authagonal ثلاث طرق لـ MFA: TOTP (تطبيقات المصادقة)، وWebAuthn (مفاتيح الأمان والقياسات الحيوية)، ورموز الاسترداد ذات الاستخدام الواحد.

إعداد TOTP

POST /api/auth/mfa/totp/setup: يعيد <code>setupToken</code> وعنوان URI لبيانات رمز QR ومفتاح إدخال يدوي. يمسح المستخدم رمز QR بتطبيق المصادقة لديه (Google Authenticator، Authy، 1Password، وغيرها)، ثم يؤكد التسجيل.

POST /api/auth/mfa/totp/confirm: يؤكد تسجيل TOTP عبر إرسال <code>setupToken</code> الناتج عن الإعداد مع رمز مكوّن من 6 أرقام من تطبيق المصادقة.

Confirm TOTP enrollment
{
  "setupToken": "SETUP_TOKEN_FROM_SETUP_RESPONSE",
  "code": "123456"
}

إعداد WebAuthn

POST /api/auth/mfa/webauthn/setup: يعيد خيارات إنشاء بيانات الاعتماد لـ WebAuthn API. يستدعي المتصفح navigator.credentials.create() بهذه الخيارات.

POST /api/auth/mfa/webauthn/confirm: يؤكد تسجيل WebAuthn عبر إرسال استجابة الإثبات من المتصفح.

رموز الاسترداد

POST /api/auth/mfa/recovery/generate: ينشئ 10 رموز استرداد من 10 أحرف تُستخدم مرة واحدة (بالتنسيق <code>XXXXX-XXXXX</code>). يمكن استخدام كل رمز مرة واحدة بالضبط لتجاوز MFA. يجب تسجيل تطبيق مصادقة أو مفتاح مرور أولًا.

تُعرض رموز الاسترداد مرة واحدة فقط

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

التحقق من MFA

POST /api/auth/mfa/verify: يكمل تحدي MFA بعد تسجيل دخول ناجح بكلمة المرور.

الحقلمطلوبالوصف
challengeIdنعممعرّف التحدي من استجابة تسجيل الدخول
methodنعم"totp" أو "recovery" أو "webauthn"
codeTOTP / الاستردادرمز TOTP من 6 أرقام أو رمز استرداد (XXXXX-XXXXX)
assertionWebAuthnاستجابة التأكيد من navigator.credentials.get()

حالة MFA

GET /api/auth/mfa/status: يعيد طرق MFA المسجَّلة حاليًا للمستخدم.

تدفق تسجيل الدخول عبر SSO

يدعم Authagonal اتصالات SSO القائمة على SAML 2.0 وعلى OIDC. يكتشف التوجيه القائم على النطاق تلقائيًا أي موفّر SSO يجب استخدامه بناءً على عنوان البريد الإلكتروني للمستخدم.

فحص SSO

GET /api/auth/[email protected]

الحقلالنوعالوصف
ssoRequiredbooleanما إذا كان نطاق البريد الإلكتروني يتطلب SSO
providerTypestring"saml" أو "oidc"
connectionIdstringمعرّف اتصال SSO
redirectUrlstringعنوان URL الذي يُعاد توجيه المستخدم إليه لتسجيل الدخول عبر SSO

تدفق SAML

يُعاد توجيه المستخدم إلى GET /saml/{connectionId}/login الذي يرسل طلب SAML AuthnRequest إلى موفّر الهوية. يصادق موفّر الهوية المستخدم ويرسل استجابة SAML إلى نقطة نهاية خدمة استهلاك التأكيد (ACS). يتحقق Authagonal من التأكيد، وينشئ المستخدم أو يحدّثه، ويوقّع ملف تعريف ارتباط للجلسة.

تتوفر البيانات الوصفية لـ SAML لتهيئة موفّر الهوية لديك على GET /saml/{connectionId}/metadata.

تدفق OIDC

يُعاد توجيه المستخدم إلى GET /oidc/{connectionId}/login الذي يعيد التوجيه إلى موفّر الهوية الأعلى مع PKCE. بعد مصادقة المستخدم، يبادل رد النداء عند /oidc/callback رمز التفويض، ويتحقق من رمز الهوية، وينشئ المستخدم أو يحدّثه.

التزويد في الوقت المناسب (JIT): يدعم تدفقا SAML وOIDC التزويد في الوقت المناسب، وهو معطّل افتراضيًا على كل اتصال (تفعيل الإنشاء التلقائي عند أول دخول). عندما يكون مفعّلًا ولم يكن المستخدم موجودًا بالفعل في المستأجر، يُنشأ تلقائيًا من مطالبات موفّر الهوية. وإن كان موجودًا، تُحدَّث سمات ملفه الشخصي لتطابق أحدث القيم من الموفّر.

التوجيه القائم على النطاق

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

Backend-for-Frontend (BFF)

يُبقي BFF رموز OAuth خارج المتصفّح تمامًا. فلا يحمل تطبيق الصفحة الواحدة لديك سوى ملف تعريف ارتباط جلسة من نوع httpOnly، بينما يتولى عميل سرّي على خادمك الخلفي تدفق OpenID Connect ويحتفظ بالرموز على جانب الخادم.

كل ما يستطيع تطبيق الصفحة الواحدة قراءته تستطيع البرمجة النصية عبر المواقع سرقته، ويشمل ذلك رمز وصول في الذاكرة ورمز تحديث في localStorage. كما أن تخزين الرموز في المتصفّح يحدّ من مدة صلاحيتها، لأن رمز تحديث طويل العمر في متناول النصوص البرمجية يمثّل خطرًا دائمًا. ولهذا السبب بالذات توصي بهذا النمط ممارسة IETF الفضلى الحالية OAuth 2.0 for Browser-Based Apps.

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

إنشاء العميل

في البوابة، افتح العملاء واختر إنشاء تطبيق BFF. أعطِه عنوان URL الأساسي الذي يُقدَّم منه تطبيقك، مثل https://app.acme.com، فيسجّل Authagonal نيابةً عنك عميلًا سرّيًا مضبوطًا على النحو الصحيح بدلًا من أن يتركك تركّبه بنفسك:

الإعدادالقيمة
عنوان إعادة التوجيه{appBaseUrl}/bff/callback
عنوان إعادة التوجيه بعد تسجيل الخروج{appBaseUrl}/
عنوان تسجيل الخروج بالقناة الخلفية{appBaseUrl}/bff/backchannel-logout
أنواع المنحauthorization_code, refresh_token
النطاقاتopenid, profile, email, offline_access
PKCE وسرّ العميلكلاهما مطلوب

يُعرض السرّ مرة واحدة

تحمل الاستجابة clientId وclientSecret وauthority، ولا يمكن استرجاع السرّ بعد ذلك أبدًا لأن المخزَّن هو بصمته فقط. ضعه مباشرةً في إعدادات خادمك الخلفي أو في مخزن الأسرار لديك. وإذا فقدته، فأنشئ عميلًا آخر بدلًا من محاولة استرجاع هذا العميل.

اربطه بخادمك الخلفي

بيئتا تشغيل مدعومتان وتتشاركان البروتوكول الأساسي نفسه: Authagonal.Bff لـ .NET و@authagonal/bff لـ Node، والأخيرة مزوّدة بمحوّلات لـ Express وNext.js. وجّه أيًّا منهما إلى القيم التي أعطتك إياها البوابة للتو. وتحتاج حزمة Node أيضًا إلى cookieSecret خاص بك، تستخدمه لتشفير ملفات تعريف الارتباط الخاصة بها.

.NET
// dotnet add package Authagonal.Bff
builder.Services.AddAuthagonalBff(o =>
{
    o.Authority    = "https://acme.authagonal.io";       // your tenant auth host
    o.ClientId     = builder.Configuration["Bff:ClientId"]!;
    o.ClientSecret = builder.Configuration["Bff:ClientSecret"]!;
    o.Scope        = ["openid", "profile", "email", "offline_access"];
    o.PostLogoutRedirectUri = "https://app.acme.com/";
});

// Trust X-Forwarded-Proto from your ingress. With no options, UseForwardedHeaders() changes nothing.
builder.Services.Configure<ForwardedHeadersOptions>(o =>
{
    o.ForwardedHeaders = ForwardedHeaders.XForwardedProto;
    o.KnownNetworks.Clear();
    o.KnownProxies.Clear();
});

var app = builder.Build();

app.UseForwardedHeaders();   // required behind a proxy or ingress, see the note below
app.MapAuthagonalBff();
app.MapFallbackToFile("index.html");   // your SPA
app.Run();
Node (Express)
// npm install @authagonal/bff
import express from 'express';
import { authagonalBff } from '@authagonal/bff/express';

const app = express();

app.use(authagonalBff({
  authority: 'https://acme.authagonal.io',
  clientId: process.env.BFF_CLIENT_ID,
  clientSecret: process.env.BFF_CLIENT_SECRET,
  cookieSecret: process.env.BFF_COOKIE_SECRET,   // encrypts the session and login cookies
  scope: ['openid', 'profile', 'email', 'offline_access'],
  postLogoutRedirectUri: 'https://app.acme.com/',
}));

app.listen(8080);

خلف وكيل، ثِق بالترويسات المُمرَّرة

يضع كل نشر تقريبًا BFF خلف بوابة دخول أو موازِن أحمال ينهي TLS ويتحدث HTTP عاديًا مع عمليتك. وبدون معالجة الترويسات المُمرَّرة، يظن BFF أن الطلب غير آمن فيصدر ملف تعريف ارتباط الجلسة __Host- بلا خاصية Secure، فتتجاهله المتصفّحات بصمت. والعَرَض هو تسجيل دخول يكتمل بسلاسة وجلسة لا تظهر أبدًا. في .NET فعّل XForwardedProto في ForwardedHeadersOptions واستدعِ app.UseForwardedHeaders() قبل MapAuthagonalBff()، كما في المثال أعلاه: فالاستدعاء المجرد لا يثق بأي ترويسة. وتقرأ محوّلات Node الترويسة X-Forwarded-Proto بنفسها وتضع دائمًا الخاصية Secure على ملف تعريف الارتباط __Host-، فاضبط إعداد trust-proxy في إطار العمل لديك كي يكون عنوان العميل المُمرَّر إلى واجهتك البرمجية هو العنوان الحقيقي.

نقاط النهاية

تُركَّب افتراضيًا تحت /bff. ويجب أن تُقدَّم من المصدر نفسه الذي يُقدَّم منه تطبيق SPA لديك، لأن ملف تعريف ارتباط الجلسة هو httpOnly ومقيَّد بالمصدر نفسه: ضعها خلف اسم المضيف نفسه بدلًا من نطاق API منفصل.

المسارالغرض
GET /bff/login?returnUrl=/يبدأ تسجيل الدخول ويعيد التوجيه إلى Authagonal. ثم يعيد المستخدم بعد ذلك إلى returnUrl.
GET /bff/callbackعنوان إعادة التوجيه الخاص بـ OIDC. يُعالَج نيابةً عنك، ولن تكتبه أبدًا.
GET /bff/userيعيد isAuthenticated ومطالبات الجلسة وsessionExpiresAt. ويتطلب ترويسة مكافحة التزوير.
GET|POST /bff/logoutينهي الجلسة محليًا ولدى Authagonal.
POST /bff/backchannel-logoutيستقبل إشعارات تسجيل الخروج من Authagonal، فيؤدي تسجيل الخروج في مكان آخر إلى إنهاء هذه الجلسة أيضًا.

من المتصفّح

يجب أن يحمل كل طلب غير تنقّلي ترويسة ثابتة لمكافحة التزوير. وهي تحمي من تزوير الطلب عبر المواقع إلى جانب خاصية SameSite لملف تعريف الارتباط: فإرسال نموذج من موقع آخر لا يستطيع ضبط ترويسة مخصصة، لذا يُرفض أي طلب لا يحملها.

التحقق ممّن سجّل الدخول
const me = await fetch('/bff/user', {
  headers: { 'X-Authagonal-Bff': '1' },
}).then(r => r.json());

if (!me.isAuthenticated) {
  // Navigate, do not fetch: this is a redirect to your identity provider.
  window.location.href = '/bff/login?returnUrl=' + encodeURIComponent(location.pathname);
}

سجّل الدخول والخروج عبر التنقّل، لا عبر الجلب: location.href = '/bff/login'. فهذه المسارات تجيب بإعادة توجيه إلى مزوّد الهوية لديك، وسلسلة إعادة التوجيه ليست شيئًا يستطيع fetch تتبّعه على نحو مفيد.

استدعاء واجهة API لديك

يستطيع BFF توجيه واجهة API لديك تحت مساره الأساسي وإرفاق رمز وصول الجلسة أثناء المرور. فيرسل المتصفّح ملف تعريف ارتباط، وتستقبل واجهة API لديك رمز حامل تتحقق منه كالمعتاد، ولا شيء من ذلك الرمز مرئي للصفحة ولا قابل للتزوير منها. سجّل وجهة فتصل الطلبات الموجَّهة إلى /bff/api/** إليها مُصادَقًا عليها. واترك القائمة فارغة فيُعطَّل الوكيل تمامًا.

توجيه الطلبات إلى واجهة API وجهة
o.Upstreams.Add(new BffUpstream
{
    Prefix        = "/orders",                        // matches /bff/api/orders/**
    TargetBaseUrl = "https://api.internal.acme.com",
    StripPrefix   = false,                            // keep /orders in the forwarded path
});
الخيارالافتراضيالوصف
Upstreams[]واجهات API التي يوجّه إليها الوكيل الطلبات. والقائمة الفارغة تعطّل نقطة نهاية الوكيل.
Prefix/بادئة المسار بعد /bff/api التي تتولاها هذه الوجهة، مثل /orders.
TargetBaseUrl-عنوان URL الأساسي الذي تُوجَّه إليه الطلبات.
StripPrefixfalseإزالة البادئة المطابِقة قبل التوجيه. يتيح لك استخدام بادئة توجيه اصطناعية لتوزيع BFF واحد على عدة خوادم خلفية تتشارك مساحة اسم المسارات نفسها.
AllowAnonymousProxyRequestsfalseتوجيه الطلب الذي لا جلسة صالحة له بدون ترويسة Authorization بدلًا من رفضه. وذلك من أجل واجهة API تخدم المستدعين المسجَّلين والمجهولين معًا.
RequiredAuthority[]بوابة صلاحيات على هيئة أزواج type:action، مثل email:send. وعند ضبطها، يفحص الوكيل تفاصيل التفويض وفق RFC 9396 في الرمز الصادر قبل التوجيه.
AuthorityLocation-جذر locations وفق RFC 9396 الذي تُعرَف به هذه الوجهة، حين تُمنَح الصلاحية على معرّف مورد عام يختلف عن العنوان الداخلي الذي يستدعيه الوكيل.
StrictAuthorityfalseرفض الاستدعاء الذي يحمل قيد منح لا يستطيع الوكيل تقييمه بدلًا من توجيهه. فالوكيل يوجّه دون رؤية ولا يستنتج أي سياق للقيود، لذا فهذا الخيار معطّل افتراضيًا.
ExchangeRoutes[]مسارات الوكيل التي تنطلق استدعاءاتها إلى الوجهة برمز مُستبدَل مقيَّد بالسياق بدلًا من رمز الوصول الأساسي للجلسة. ويفوز أول نمط مطابق.

WebSockets

لا تستطيع مصافحة WebSocket حمل ترويسة مخصصة ولا رمز حامل، لذا لا تفيد ترويسة مكافحة التزوير ولا الوكيل. فعّل التذاكر ليتمكن تطبيق SPA من استدعاء GET /bff/ws-ticket، ووضع التذكرة القصيرة العمر ذات الاستخدام الواحد على عنوان URL للاتصال، ثم استبدالها في واجهة API لديك. سُكَّ تذكرة قبل كل اتصال مباشرةً: فهي تُحذف عند أول استخدام وتنتهي صلاحيتها خلال ثوانٍ.

الخيارالافتراضيالوصف
WsTicketsEnabledfalseيفعّل نقطة نهاية ws-ticket. معطّل افتراضيًا.
WsTicketLifetime30sمدة صلاحية التذكرة. وتبقى قصيرة عن قصد، لأنها تنتقل داخل عنوان URL.
TicketExchangeParams[]معاملات الاستعلام التي يجوز لطلب التذكرة تمريرها إلى عملية استبدال الرمز، فتُقيَّد التذكرة بذلك السياق بدلًا من أن تكون صالحة لكل شيء.

تسليم رمز إلى المتصفّح عن قصد

الغاية كلها من BFF أن المتصفّح لا يحمل أي رمز، لذا فهذا الخيار اختياري وضيّق. وهو موجود للحالة الوحيدة التي لا يبلغها نموذج ملف تعريف الارتباط: خادم موارد على مصدر آخر، مثل تطبيق تُضمّنه في إطار iframe، ولا بد من استدعائه برمز حامل. وعند تفعيله، يعيد GET /bff/token?resource=… رمزًا مُستبدَلًا: أي رمز الجلسة بعد تضييق نطاقه إلى مورد واحد مدرج في قائمة السماح وتقييده بأي معامل سياق مدرج في قائمة السماح. ولا يرى المتصفّح أبدًا رمز الجلسة نفسه، وما يحصل عليه قصير العمر وذو جمهور واحد. ويُرفض أي طلب يذكر موردًا خارج قائمة السماح، وهو ما يمنع أن يكون هذا مصدرًا عامًا لسَكّ الرموز.

الخيارالافتراضيالوصف
TokenEndpointEnabledfalseيفعّل نقطة نهاية الرمز. معطّل افتراضيًا.
TokenEndpointResources[]قيم المورد التي يجوز أن يُوجَّه إليها الرمز. وما عداها يُرفض.
TokenEndpointExchangeParams[]معاملات الاستعلام التي تُمرَّر إلى عملية الاستبدال بوصفها قيودًا سياقية، مثل project_id.

خدمة عدة مستأجرين من BFF واحد

اضبط معامل استعلام للمستأجر فيخدم نشرٌ واحد مستأجرين كثيرين: يختار /bff/login?slug=acme المستأجر، ويوفّر محدِّدٌ مضيفَ المصادقة وبيانات اعتماد العميل الخاصة بذلك المستأجر، وينتقل المفتاح مع ملف تعريف ارتباط الترابط إلى الجلسة، ويحدد تسجيل الخروج بالقناة الخلفية المستأجرَ من مُصدِر الرمز. ويُبقي المحدِّد الافتراضي سلوك المستأجر الواحد مطابقًا بايتًا ببايت، فلا تدفع شيئًا مقابل هذا ما لم تستخدمه.

تشغيل أكثر من نسخة

تعيش الجلسات خلف IBffSessionStore، وهو يستخدم افتراضيًا ذاكرة تخزين مؤقت داخل العملية. وهذا مناسب لنسخة واحدة وخاطئ لعدة نسخ: فالمستخدم الذي يصل طلبه التالي إلى نسخة أخرى يخرج من جلسته. سجّل مخزنًا مشتركًا، مثل Redis عبر IDistributedCache، قبل إضافة BFF.

المخزن المشترك وحده لا يكفي

تحتاج أيضًا إلى قفل تحديث يعمل عبر النسخ. فآلية الرحلة الواحدة للتحديث محلية داخل العملية، بينما تعيش الجلسة ورمز التحديث المتناوب الخاص بها في المخزن الذي تتشاركه كل نسخة. فقد تقرأ نسختان الجلسة نفسها، وتقرر كلتاهما أنها بحاجة إلى تحديث، وتستبدل كلتاهما رمز التحديث نفسه. وهذا لا يمكن تمييزه عن إعادة تشغيل رمز مسروق، والاستجابة الصحيحة لإعادة التشغيل هي إبطال عائلة المنح كاملةً، لذا فإن BFF متعدد النسخ بلا قفل قد يُخرج المستخدمين من جلساتهم بشكل روتيني. وفّره بأي من الطريقتين: سجّل ILeaseProvider عبر التجميع العنقودي، أو نفّذ IBffRefreshLockStore على مخزن الجلسات لديك، وهو كتابة مشروطة بمدة صلاحية وأقصر طريق إن كنت تشغّل Redis أصلًا. وأي BFF يبدو مخزنه مشتركًا وليس لديه قفل ينبّه إلى ذلك عند الإقلاع بدلًا من أن يتركك تكتشفه من تذكرة دعم.

خيارات تستحق المعرفة

المجموعة الكاملة، بصيغة .NET. وتأخذ حزمة Node الخيارات الأساسية بصيغة camelCase، فيصبح BasePath هو basePath، وSessionLifetime هو sessionLifetimeSeconds. أما PersistentCookie وCorrelationLifetime (الثابت عند 15 دقيقة في Node) وLoginPassthroughParams فهي خاصة بـ .NET فقط.

الخيارالافتراضيالوصف
Authority-مضيف المصادقة الخاص بمستأجرك. وتُكتشف منه بيانات تعريف OIDC. وهو مطلوب إلا إذا كنت متعدد المستأجرين، حيث يوفّره المحدِّد.
ClientId-معرّف العميل السرّي المسجَّل لهذا الـ BFF.
ClientSecret-سرّ العميل. وBFF عميل سرّي، لذا فهذا مطلوب.
Scopeopenid profile offline_accessالنطاقات المطلوبة. ضمّن offline_access وإلا فلا وجود لرمز تحديث وتنتهي الجلسات بانتهاء رمز الوصول.
BasePath/bffالمكان الذي تُركَّب فيه مسارات BFF.
CallbackPath/bff/callbackمسار عنوان إعادة التوجيه الخاص بـ OIDC. ويجب أن يطابق ما سُجِّل به العميل.
CookieName__Host-agbffاسم ملف تعريف ارتباط الجلسة. البادئة __Host- تتطلب HTTPS، لذا يحتاج التطوير المحلي عبر HTTP العادي إلى اسم مختلف.
SessionLifetime8hالمدة التي يجوز أن تعيشها الجلسة. اضبطها لتطابق المدة المطلقة لرمز التحديث لديك، وإلا خرج المستخدم الخامل من جلسته وهو يحمل بيانات اعتماد كانت ما تزال صالحة.
PersistentCookiefalseما إذا كان ملف تعريف الارتباط يبقى بعد إغلاق المتصفّح. ويبقى رمز التحديث على جانب الخادم في الحالتين.
CorrelationLifetime30mالمدة المسموح بها لتسجيل الدخول بين بدئه ورد النداء. وهي تحدّ عمر ملف تعريف الارتباط الحامل لـ state وnonce ومُحقِّق PKCE، فالحالة التي عليها أن تصمد أمامها هي مستخدم يترك شاشة تسجيل الدخول مفتوحة ثم يعود إليها.
RefreshThresholdSeconds60عدد الثواني المتبقية قبل انتهاء الصلاحية التي يُحدَّث عندها رمز الوصول.
AntiForgeryHeaderX-Authagonal-Bffاسم الترويسة التي يجب أن يرسلها المتصفّح في الطلبات غير التنقّلية.
PostLogoutRedirectUri-المكان الذي يصل إليه المتصفّح بعد اكتمال تسجيل الخروج.
ReturnUrlAllowlist[]المصادر المطلقة التي يجوز أن يستهدفها returnUrl غير النسبي. أما المسارات النسبية فمسموح بها دائمًا، وكل ما عداها يُحوَّل قسرًا إلى /، فلا يمكن بلوغ إعادة توجيه مفتوحة عبر مسار تسجيل الدخول.
LoginPassthroughParams[]معاملات الاستعلام التي تُمرَّر من /bff/login إلى طلب authorize، مثل prompt، حتى يتمكن رابط البدء من التوجيه إلى التسجيل بدلًا من تسجيل الدخول.
TenantQueryParam-اضبطه لخدمة عدة مستأجرين من BFF واحد. انظر أعلاه.

بيئتا التشغيل تتصرفان بالطريقة نفسها

تنفّذ حزمتا .NET وNode عقد البروتوكول الأساسي نفسه، فتتطابق عمليات تسجيل الدخول ورد النداء (callback) والمستخدم وتسجيل الخروج وتسجيل الخروج عبر القناة الخلفية، وملف تعريف الارتباط، وترويسة مكافحة التزوير، وسلوك التحديث، والوكيل الأساسي إلى الخادم الأصلي. أما تذاكر WebSocket، ونقطة نهاية الرموز، ومسارات التبادل، وStripPrefix، وبوابات السلطة (authority)، والوكالة المجهولة فهي خاصة بـ .NET فقط. والأسماء أعلاه مكتوبة بصيغة .NET، بينما تستخدم Node مقابلاتها بصيغة camelCase.

كل شيء قابل للاستبدال

الأجزاء عبارة عن واجهات، فيمكنك نقل BFF إلى بنيتك التحتية الخاصة دون تفريعه: IBffSessionStore لمكان عيش الجلسات، وICookieProtector لتشفير ملف تعريف الارتباط (ASP.NET Data Protection افتراضيًا)، وITokenClient للتخاطب مع نقطتي نهاية الرموز والإبطال. كما يمكن لـ BFF واحد أن يخدم عدة مستأجرين عبر IBffTenantResolver، فيختار المستأجر من معامل استعلام عند تسجيل الدخول ويحدده من مُصدِر الرمز عند تسجيل الخروج بالقناة الخلفية.

أدِر بوابتك من مساعد ذكاء اصطناعي

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

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

تفعيله

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

عنوان URL الخاص بـ MCP لديك
https://portal-api.authagonal.io/api/v1/mcp/{your-tenant}

كيف يحصل المساعد على الإذن

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

ما يستطيع المساعد فعله

بالضبط ما يستطيع الشخص الذي ربطه فعله، ويُحسم ذلك في كل استدعاء بناءً على رمزه هو. يحصل وكيل tenant:support على الأدوات التشخيصية والأدوات اليومية؛ أما أدوات المسؤول فليست مخفية عنه فحسب، بل تُرفَض إن سمّاها مباشرة. وكل ما هو محجوب داخل البوابة يبقى محجوبًا: فتغيير عنوان البريد الإلكتروني لمستخدم يتطلب دور المسؤول هناك، ويتطلبه هنا أيضًا.

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

الأدوات

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

الأداةالدورما تفعله
find_userالدعمابحث عن المستخدمين بالبريد الإلكتروني أو بادئة الاسم أو المعرّف. وهي نقطة البداية لكل ما عداها.
get_userالدعممستخدم واحد بتفاصيله الكاملة، بما في ذلك ما إذا كان نشطًا ومؤكَّدًا ومقفلًا.
get_user_mfaالدعمما العوامل الثانية التي سجّلها شخص ما.
get_user_sessionsالدعمأين يسجّل المستخدم دخوله حاليًا.
search_auditالدعمابحث في سجل التدقيق حسب المنفِّذ أو الإجراء أو الكيان الذي جرى عليه الإجراء.
list_usersالدعماعرض الدليل، مع إمكانية تصفيته على مؤسسة واحدة.
get_user_statsالدعمكم عدد المستخدمين لديك وكم منهم يستخدم عاملًا ثانيًا.
invite_userالدعمادعُ شخصًا بالبريد الإلكتروني.
resend_inviteالدعمأعد إرسال دعوة.
send_verification_emailالدعمأعد إرسال رسالة التحقق من البريد الإلكتروني.
update_userالدعمحدّث ملفًا شخصيًا. أما تغيير عنوان البريد الإلكتروني فما زال يتطلب دور المسؤول.
revoke_user_sessionsالدعمسجّل خروج مستخدم من كل مكان.
list_rolesالمسؤولالأدوار المعرَّفة في المستأجر لديك.
list_role_membersالمسؤولمن يحمل دورًا معيّنًا.
assign_roleالمسؤولامنح مستخدمًا دورًا.
unassign_roleالمسؤولاسحب دورًا.
reset_user_mfaالمسؤولأزِل كل عامل ثانٍ، لمن فقد تطبيق المصادقة لديه.
get_settingsالمسؤولإعدادات المستأجر لديك.
list_sso_connectionsالمسؤولاتصالات SSO لديك والنطاقات التي تغطيها.
list_organizationsالمسؤولالمؤسسات في المستأجر لديك، صفحة واحدة في كل مرة.
get_organizationالمسؤولمؤسسة واحدة بمعرّفها أو slug، مع نطاقات بريدها الإلكتروني.
create_organizationالمسؤولتنشئ مؤسسة. الـ slug دائم.
update_organizationالمسؤولتغيّر اسم المؤسسة أو خيارات السياسة أو البيانات الوصفية أو العلامة التجارية. لا يمكن تغيير الـ slug.
delete_organizationالمسؤولتحذف مؤسسة وجميع عضوياتها.
list_organization_membersالمسؤولأعضاء المؤسسة، صفحة واحدة في كل مرة.
add_organization_memberالمسؤولتضيف مستخدمًا إلى مؤسسة.
update_organization_memberالمسؤولتغيّر حالة عضو أو أدواره داخل مؤسسة.
remove_organization_memberالمسؤولتزيل مستخدمًا من مؤسسة.
add_organization_domainالمسؤولتطالب بنطاق بريد إلكتروني لمؤسسة. تعيد سجل DNS من نوع TXT الواجب نشره.
verify_organization_domainالمسؤولتتحقق من سجل TXT وتضع علامة التحقق على النطاق. يمكن تكرارها بأمان.
remove_organization_domainالمسؤولتتخلى عن المطالبة بنطاق. يبقى الأعضاء الحاليون.
list_user_organizationsالمسؤولالمؤسسات التي ينتمي إليها مستخدم، مع حالته وأدواره في كل منها.
list_clientsالمطوّرعملاء OAuth المسجَّلون في المستأجر لديك.

الأدوات موسومة بالقراءة أو الكتابة

تخبر كل أداة عميلك بما إذا كانت تقرأ فقط، وما إذا كانت تغيّر شيئًا، وما إذا كان ذلك التغيير مدمّرًا. والعميل الجيد يستخدم هذا لتنفيذ عملية بحث دون مقاطعتك، وللتمهّل قبل شيء مثل إزالة عامل ثانٍ. عامِله بوصفه تسهيلًا لا ضابطًا: فالذي يقرر فعليًا ما يُسمح للمساعد بفعله هو دورك أنت، ويُفحص في كل استدعاء.

ما لم يُشمَل بعد

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

مصادقة خادم MCP

إذا كنت تعرض خادم Model Context Protocol، فبإمكان Authagonal أن يكون خادم التفويض خلفه. يتصل مساعد ذكاء اصطناعي، ويسجّل الشخص الذي يقف خلفه الدخول ويمنح الوصول، ويستقبل خادمك رمزًا حاملًا عاديًا تتحقق منه كما تتحقق من أي API آخر.

البديل هو مفتاح API يُلصق في تهيئة المساعد، وهو بيانات اعتماد لا مستخدم خلفه، ولا تاريخ انتهاء له، ولا خطوة موافقة فيه، ولا سبيل معه لإبطال موصّل واحد دون تدوير المفتاح للجميع. أما تنفيذه بواسطة OAuth فيعني أن المنحة تعود إلى شخص محدد بالاسم، وتظهر في سجل التدقيق لديك، ويمكن إبطالها من البوابة دون المساس بأي شيء آخر.

كيف يتم الاتصال

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

الخطوةما يحدث
1يستدعي الموصّل خادم MCP لديك دون رمز، فيتلقى استجابة 401 تحدد أين يبحث.
2يجلب بيانات تعريف المورد المحمي لديك، وهي التي تسمّي مستأجر Authagonal الخاص بك بوصفه خادم التفويض.
3يجلب بيانات تعريف خادم التفويض للمستأجر، وبما أنه لم يُسجَّل في أي مكان من قبل، فإنه يسجّل نفسه.
4يرسل المستخدم لتسجيل الدخول والموافقة على الوصول، مسمّيًا خادم MCP لديك بوصفه المورد الذي يريد رمزًا له.
5يستدعي خادمك مجددًا بالرمز الحامل الناتج، وهو رمز مقصور على خادمك وعلى ذلك المستخدم.

لا شيء في هذا التسلسل خاص بـ Authagonal: إنها مواصفة تفويض MCP، المبنية على RFC 9728 لبيانات تعريف المورد، وRFC 8414 لاكتشاف خادم التفويض، وRFC 7591 للتسجيل، وRFC 8707 لتسمية المورد. والموصّل الذي يتبع المواصفة يعمل دون معاملتنا كحالة خاصة.

دع الموصّلات تسجّل نفسها

الموصّل الذي لم تلتقِ به من قبل لا يستطيع استخدام عميل أنشأته يدويًا، فيسجّل عميلًا أثناء التشغيل. وهذا معطّل افتراضيًا. فعّل التسجيل الديناميكي للعملاء في الإعدادات فتظهر نقطة نهاية التسجيل في مستند الاكتشاف لديك؛ واتركه معطّلًا فلا يُعلَن عن نقطة النهاية وترفض الطلبات. وتفعيله يفتح التسجيل لمستأجرك وحده، ولا يفتحه لأي مستأجر آخر أبدًا.

الضابطما يحدث
أنواع المنحلا يمكن تسجيل سوى تدفقي رمز التفويض والتحديث. ولا يستطيع التسجيل الذاتي سَكّ عميل من آلة إلى آلة يتجاوز المستخدم تمامًا.
PKCEمفروض على كل عميل مسجَّل، مهما طلب التسجيل.
الموافقةمفروضة أيضًا. فلا يستطيع الموصّل المسجَّل الحصول على رمز حتى يرى شخصٌ ما يطلبه ويوافق عليه.
النطاقاتالنطاقات المدمجة في OIDC متاحة دائمًا. وبخلافها، لا يجوز لعميل مسجِّل لنفسه أن يطلب إلا نطاقًا اسمه mcp، وذلك فقط بعد أن يعرّفه مستأجرك دون قيود أدوار. ولا يمكن لعميل مسجِّل لنفسه طلب roles وgroups.
حد المعدلعشر عمليات تسجيل لكل عنوان IP في الساعة، حتى لا تُستخدم نقطة نهاية مفتوحة في ملء مخزن العملاء لديك.

يُخدَم كلا مساري الاكتشاف

يحدّد عملاء MCP خادم التفويض عبر /.well-known/oauth-authorization-server (RFC 8414)، بينما يستخدم عملاء OIDC المسار /.well-known/openid-configuration. ويستجيب مستأجرك على المسارين بالبيانات التعريفية نفسها، فيجدك الموصّل الذي يتبع مواصفة MCP دون أن يُخبَر أين يبحث.

ما ينفّذه خادم MCP لديك

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

بيانات تعريف المورد المحمي
GET https://your-app.example/.well-known/oauth-protected-resource

{
  "resource": "https://your-app.example/mcp",
  "authorization_servers": ["https://acme.authagonal.io"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["mcp"]
}

ثانيًا، عندما يصل استدعاء دون رمز صالح، أجب بـ 401 مع ترويسة WWW-Authenticate تشير إلى تلك البيانات التعريفية. هذه الترويسة هي ما يحوّل الرفض إلى اتصال: فبدونها لا يملك العميل أي وسيلة لاكتشاف أين يصادق، ويفشل ببساطة.

التحقق من الرمز
// Validate the connector's token like any other resource server.
builder.Services.AddAuthentication().AddJwtBearer("McpBearer", o =>
{
    o.Authority = "https://acme.authagonal.io";              // your tenant
    o.TokenValidationParameters.ValidAudience = "https://your-app.example/mcp";
});

// Unauthenticated? Point the connector at the metadata rather than just refusing.
http.Response.Headers.WWWAuthenticate =
    "Bearer resource_metadata=\"https://your-app.example/.well-known/oauth-protected-resource\"";
return Results.Unauthorized();

تحقّق من الجمهور، لا من التوقيع وحده

تحقّق من أن الرمز أُصدِر لخادمك أنت. فالموصّل يسمّي خادم MCP لديك بوصفه المورد، ومن ثم يكون جمهور الرمز هو عنوان URL لموردك. وخادم الموارد الذي يفحص التوقيع والمُصدِر فقط سيقبل رمزًا سُكَّ لمورد مختلف داخل المستأجر نفسه، وهكذا يصبح وصول موصّل ما وصولًا لموصّل آخر.

النطاقات والخطط والإبطال

عرّف نطاقًا اسمه mcp في صفحة النطاقات لديك، دون قيود أدوار، فيصبح بإمكان موصّل مسجِّل لنفسه طلبه، ويظهر على شاشة الموافقة ليرى المستخدم ما يوافق عليه. وصاحب الرمز (subject) هو الشخص الذي سجّل الدخول، فيستطيع خادمك أن يقرر ما يُسمح لهذا الشخص بالذات بفعله بدلًا من معاملة كل موصّل بالطريقة نفسها. ولا يمكن لموصّل مسجِّل لنفسه طلب النطاقين roles أو groups، لذا ابحث عنهما من جهتك بدلًا من توقّعهما في الرمز.

ولأنها منحة OAuth عادية، يعمل الإبطال بالطريقة العادية: يزيل المستخدم الموصّل من صفحة التطبيقات المُصرَّح لها في حسابه، مما يُسقط منحته ورمز التحديث الخاص به فلا يستطيع التجديد. وتُرفض رموز الوصول الحالية الخاصة به فورًا من قِبل /connect/introspect و/connect/userinfo، أما الخادم الذي يكتفي بالتحقق من JWT محليًا فيقبل الرمز حتى تنتهي صلاحيته. ويسجّل سجل التدقيق كل تسجيل دخول مع العميل الذي جرى من أجله.

الإعدادما يحدث
Dynamic client registrationإعداد في البوابة يسمح للموصّلات بتسجيل نفسها. معطّل افتراضيًا.
mcpالنطاق الوحيد الذي يتجاوز نطاقات OIDC المدمجة والذي يجوز لعميل مسجِّل لنفسه أن يطلبه. عرّفه في مستأجرك، دون قيود أدوار، لإتاحته.
resourceالمعامل الذي يرسله الموصّل ليسمّي خادم MCP لديك، وهو ما يضيّق جمهور الرمز ليقتصر عليه.

بناء واجهة تسجيل دخول مخصصة

استبدل شاشات تسجيل الدخول والتسجيل وإعادة تعيين كلمة المرور وMFA المُستضافة من Authagonal بواجهتك الخاصة، بينما يواصل Authagonal التعامل مع المصادقة وMFA وSSO والجلسات وإصدار الرموز. مساران: استخدم مكتبة مكوّنات React لدينا، أو استدعِ واجهة API للمصادقة مباشرةً من أي إطار عمل. وهي ميزة اختيارية: فعّل أولاً واجهة تسجيل دخول مخصصة ضمن الإعدادات → الجلسة.

A fully customized hosted login page with a tenant logo, brand color, and support email in the footer

شرط مسبق: نطاق مخصص على جذرك

جلسة تسجيل الدخول هي ملف تعريف ارتباط من الطرف الأول، لذا يجب أن تشترك واجهتك وخادم مصادقة Authagonal في نطاق قابل للتسجيل. وجّه نطاق مصادقة مخصصاً إلى Authagonal على الجذر نفسه الذي يعمل عليه تطبيقك، مثل المصادقة على login.acme.com والتطبيق على app.acme.com. ويبقى إعداد واجهة تسجيل الدخول المخصصة معطّلاً حتى يوجد نطاق مخصص نشط.

واجهتكمضيف المصادقةيعمل؟
app.acme.comlogin.acme.com✅ الجذر نفسه
acme.comauth.acme.com✅ الجذر نفسه
app.acme.comacme.authagonal.io❌ عبر المواقع
myapp.iologin.acme.com❌ عبر المواقع

لماذا يُشترط نطاق مخصص

ملف تعريف ارتباط الجلسة عبر المواقع سيكون ملف تعريف ارتباط من طرف ثالث، وهو ما تتخلّص منه المتصفحات (Safari وChrome) تدريجياً. وإبقاء المصادقة على جذرك الخاص يجعل ملف تعريف الارتباط من الطرف الأول وجاهزاً للمستقبل، وهو ما تفرضه المنصة: لا تُقبل استدعاءات المصادقة عبر الأصول إلا من أصل يشترك في النطاق الجذر لمضيف المصادقة.

لا حاجة إلى أي إعداد CORS في العميل لاستدعاءات /api/auth: فبمجرد تفعيل واجهة تسجيل دخول مخصصة، يُقبل تلقائيًا أي أصل على النطاق القابل للتسجيل نفسه لنطاق المصادقة لديك. أضف أصل واجهتك (مثل https://app.acme.com) إلى أصول CORS المسموح بها للعميل (العملاء → عناوين URI) فقط إذا كان المتصفح يُجري تبادل الرموز أيضًا.

React: ‏@authagonal/login

npm i @authagonal/login يشحن منطق المصادقة وواجهة المستخدم في حزمة واحدة، وهي نفسها التي بُني عليها تسجيل الدخول المُستضاف من Authagonal. اختر مستواك:

  • تطبيق كامل، أدرج App ونسّقه عبر العلامة التجارية.
  • تركيب الصفحات، استخدم LoginPage وMfaChallengePage وResetPasswordPage… داخل تخطيطك الخاص.
  • العناصر الأولية والمنطق، ابنِ شاشاتك الخاصة باستخدام AuthLayout/Button/Input وعميل API (login وmfaVerify وforgotPassword …).
شاشة مخصصة تستخدم واجهة API الخاصة بـ @authagonal/login
import { AuthLayout, Input, Button, login, ApiRequestError } from '@authagonal/login';

// returnUrl: the /connect/authorize URL your login page was opened with
function MyLogin({ returnUrl }: { returnUrl: string }) {
  async function onSubmit(email: string, password: string) {
    try {
      const res = await login(email, password, returnUrl);  // POST /api/auth/login (sets the session cookie)
      if (res.mfaRequired) {/* render your MFA step, then mfaVerify(res.challengeId!, 'totp', code) */}
      else if (res.mfaSetupRequired) {/* enrol first: mfaTotpSetup(res.setupToken) */}
      else window.location.href = returnUrl;                 // resume /connect/authorize
    } catch (e) {
      if (e instanceof ApiRequestError) {/* show e.message; e.error is the error code */}
    }
  }
  return <AuthLayout>{/* your own markup + <Input/> <Button/> */}</AuthLayout>;
}

أي إطار عمل: استدعِ واجهة API للمصادقة

لست على React؟ استدعِ نقاط نهاية تدفق المصادقة مباشرةً (تحت /api/auth)، ثم سلّم إلى تدفق OIDC القياسي /connect/authorize. أرسل credentials: 'include' كي يُخزَّن ملف تعريف ارتباط الجلسة.

نقطة النهايةالغرض
POST /api/auth/loginالمصادقة؛ تعيد mfaRequired أو عنوان URL للعودة
POST /api/auth/registerالتسجيل بالخدمة الذاتية (عند تفعيله)
POST /api/auth/forgot-passwordبدء إعادة تعيين كلمة المرور
POST /api/auth/reset-passwordإتمام إعادة تعيين كلمة المرور
GET /api/auth/password-policyسياسة كلمة المرور (لعرض القواعد)
POST /api/auth/mfa/*إعداد MFA والتحقق منه (TOTP وWebAuthn والاسترداد)

استخدم credentials: 'include'

الجلسة هي ملف تعريف ارتباط، لذا يجب أن ترسل عمليات الجلب لديك بيانات الاعتماد. ولا تنجح الاستدعاءات عبر الأصول إلا عند تفعيل واجهة تسجيل الدخول المخصصة واشتراك أصلك في النطاق الجذر لمضيف المصادقة، وإلا فتُرفض برمز 403.
صادِق، ثم سلّم إلى OIDC
# 1. Authenticate (browser fetch; credentials:'include' so the session cookie is stored)
curl -i -X POST https://login.acme.com/api/auth/login \
  -H "Content-Type: application/json" \
  -H "Origin: https://app.acme.com" \
  --data '{"email":"[email protected]","password":"..."}'
# (handle {"mfaRequired":true} → POST /api/auth/mfa/verify, then continue)

# 2. Hand off to the OAuth flow: top-level navigation to the authorize endpoint with PKCE:
# https://login.acme.com/connect/authorize?client_id=my-app&redirect_uri=...&response_type=code
#   &scope=openid%20profile%20email&code_challenge=...&code_challenge_method=S256
# The session cookie (same-site) authenticates the user; you get back a code → exchange at /connect/token.

مستأجر واحد، وعملاء كثيرون

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

البنية

  • منظمة واحدة لكل عميل، داخل مستأجر واحد.
  • نطاق تسجيل دخول واحد بعلامة تجارية لكل عميل، مثبّت كلٌّ منها على منظمة ذلك العميل، فلا يمكن لتسجيل الدخول عليه أن يُصدر رمزًا إلا لتلك المنظمة.
  • يُقدَّم التطبيق أيضًا على مضيف لكل عميل، كلها من النشر نفسه: لا شيء في الشيفرة أو البناء أو الصورة يختلف بين العملاء.
  • يختار الطرف المعتمِد سلطته من المضيف الذي يعمل عليه، لا من ثابت وقت البناء: تربط الحزمة نفسها نفسها بنطاق تسجيل دخول مختلف بحسب مضيف العميل الذي قدّمها.

خطوة بخطوة

زوّد العميل. استدعِ نقطة نهاية التزويد التصريحي بمواصفة تسمّي المنظمة الجديدة ونطاقها. الاستدعاء متكرر الأثر نفسه (idempotent) ومحدد بالأقسام.

مواصفة التزويد
{
  "organizations": [
    { "slug": "acme", "name": "Acme Pty Ltd" }
  ],
  "customDomains": [
    { "domain": "login.acme.example", "organizationSlug": "acme" }
  ]
}

وجّه DNS العميل إلى المستأجر. سجل CNAME واحد من نطاق العميل نفسه، يثبت التحكم والنية، دون رمز TXT.

CNAME record
_authagonal-challenge.login.acme.example.  CNAME  <slug>.<platformDomain>.

هل هو في حساب Cloudflare نفسه الخاص بالمنصة؟

يجب أن يكون السجل DNS فقط (دون وكيل)، فسجل CNAME بوكيل بين نطاقين في الحساب نفسه لا يصل أبدًا إلى اسم المضيف المخصص SaaS الخاص بالمنصة. أما نطاق العميل في حساب مختلف فليس فيه مفتاح وكيل يمكن ضبطه خطأً أصلًا.

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

oidc.ts
export function resolveCustomer(): { authority: string; clientId: string } {
  const cfg = getConfig();
  const customer = cfg.customers?.[window.location.host];
  if (customer) return customer;
  const baseDomain = cfg.baseDomain || window.location.hostname.replace(/^consumer\./, '');
  return { authority: `https://${cfg.tenantSlug}.${baseDomain}`, clientId: cfg.clientId };
}

لا يطلب العميل (client) أي شيء خاص بالمنظمة: لا معامل organization ولا نطاق (scope) لكل عميل. ويتولى تثبيت النطاق تحديد المنظمة بالكامل من جهة الخادم، وهذا ما يجعل عبارة «التطبيق هو الشيفرة نفسها لكل عميل» صحيحة فعلًا.

ما يراه العميل

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

يُرفض مستخدم العميل A الذي يحاول تسجيل الدخول على مضيف العميل B، ولا تُعرض له بيانات العميل B، وذلك بإحدى صورتين بحسب كيفية نشوء التعارض:

  • لا يرسل الطرف المعتمِد شيئًا ويصل ببساطة إلى النطاق المثبّت: يوفر التثبيت المنظمة نيابةً عن المستخدم، فيصبح التحديد صريحًا، ويُرفض مستخدم العميل A الذي لا عضوية له في B عند النقطة التي سيُصدَر فيها الرمز.
  • يسمّي الطرف المعتمِد منظمة مختلفة بنفسه، فيرفضه مباشرةً وسيط تثبيت النطاق بالخطأ 400، قبل عرض أي صفحة تسجيل دخول.

رفض العضوية يعيد التوجيه إلى التطبيق

الصورة الأولى أعلاه ليست صفحة تسجيل دخول معطّلة، بل إعادة توجيه OIDC عادية بـ error=access_denied إلى redirect_uri الخاص بالطرف المعتمِد نفسه، مع وصف يسمّي بالضبط عضوية أي منظمة كانت مفقودة.

ضم العميل رقم N+1

عندما يقود Terraform استدعاء التزويد، يصبح ضم عميل آخر تعديلًا في ملف واحد: إدخالًا آخر في مصفوفة organizations، وإدخال نطاق آخر يثبّته، وسجل DNS آخر. لا شيء يتغير في التطبيق أو نشره أو بنائه، ويلتقط المحلِّل المعتمد على المضيف العميل الجديد لحظة وجود إدخاله في الإعدادات.

التنفيذ المرجعي

يختبر مستأجر تطويري دائم هذا النمط كاملًا من البداية إلى النهاية على نطاقي عميلين حقيقيين، مع مجموعة اختبارات شاملة (end-to-end) تزوّد الأعضاء وتفحص العلامة التجارية ومطالبة org_id وتتحقق من صورتي الرفض أعلاه: توثيق قابل للتنفيذ، وليس مجرد وصف.

شغّله محليًا
cd e2e-consumer && DOMAIN=authagonal.dev npx playwright test organizations-domains

تعمل المجموعة افتراضيًا كغيرها من المواصفات، ويمكن تخطيها في بيئة لم تُزوَّد فيها النطاقات المرجعية، لأنها المواصفة الوحيدة في المجموعة التي تعتمد على بنية تحتية خارج سيطرة المستودع نفسه.

الخطط والحدود

يقدّم Authagonal خطة مجانية وأربعة مستويات مدفوعة. تشمل كل خطة جميع ميزات المصادقة. وتختلف الخطط في حد المستخدمين النشطين شهرياً (MAU) وتسعير التجاوز، وتقتصر الخطة المجانية على دعم المجتمع، دون مكتب دعم المستأجر.

مستويات الخطط

الخطةحد MAUالتجاوزتكلفة التجاوز/المستخدم
مجاني250لا—
Starter1,000لا—
Pro5,000نعم$0.04/مستخدم
Scale25,000نعم$0.025/مستخدم
Enterprise100,000نعم$0.015/مستخدم

المستخدمون النشطون شهرياً (MAU)

المستخدم النشط شهرياً هو أي مستخدم فريد يصادق بنجاح مرة واحدة على الأقل خلال شهر تقويمي (UTC). أما المستخدمون المُزوَّدون عبر SCIM ولم يسجّلوا الدخول فلا يُحتسبون ضمن إجمالي MAU لديك.

التجاوز: إذا كانت خطتك تدعم التجاوز (Pro وما فوقها) وكان التجاوز مفعّلًا لمستأجرك (وهو معطّل افتراضيًا)، يُحتسب المستخدمون الذين يتجاوزون حد MAU بالسعر لكل مستخدم المبيّن في جدول الخطط أعلاه. ويحدّد سقف التجاوز الحد الأقصى لعدد المستخدمين الإضافيين المسموح بهم فوق الحد.

التطبيق: إذا كانت خطتك لا تدعم التجاوز (Free وStarter) أو لم يكن التجاوز مفعّلًا، يحتفظ المستخدمون الذين سجّلوا الدخول بالفعل هذا الشهر بإمكانية الوصول دائمًا. وعندما يتجاوز المستأجر حده لأول مرة، تبدأ فترة سماح مدتها 10 أيام يظل بإمكان المستخدمين الجدد خلالها تسجيل الدخول. وبعدها، يُرفض المستخدمون الذين لم يسجّلوا الدخول هذا الشهر حتى الشهر التالي أو حتى تُرقّي خطتك.

مجموعة الميزات الكاملة في كل خطة

تشمل جميع الخطط مجموعة الميزات الكاملة: SSO وSCIM وMFA والنطاقات المخصصة والعلامة التجارية وخطافات الويب وسجل التدقيق والبوابة.