انتقل إلى المحتوى

المصادقة والصلاحيات

تستخدم جميع منصّات المنظومة نموذج مصادقة واحدًا. وتشرح هذه الصفحة ذلك النموذج، وتقدّم إرشادًا عمليًا للجهات المعتمِدة (RP) المنضمّة حديثًا.

نظرة عامة على النموذج

sequenceDiagram
    participant U as المستخدم
    participant RP as تطبيق الجهة المعتمِدة
    participant SSO as Gerege SSO
    participant EID as eID Mongolia
    participant P as الهاتف

    U->>RP: يضغط «تسجيل الدخول»
    RP->>SSO: Authorization request (code + PKCE)
    SSO->>EID: بدء الدخول بـ eID
    EID->>P: رمز QR / رابط عميق / إشعار
    P-->>EID: موافقة بـ PIN1
    EID-->>SSO: تم التعرّف على المواطن
    SSO-->>RP: Authorization code
    RP->>SSO: code + code_verifier ← الرموز
    SSO-->>RP: access + refresh + id_token
    RP->>SSO: /userinfo
    SSO-->>RP: بيانات المستخدم

المبدأ الجوهري: لا تصل الجهة المعتمِدة إلى eID مباشرةً إطلاقًا؛ فكل شيء يمرّ عبر الدخول الموحّد.

طرائق الدخول

الطريقة النوع ملاحظة
eID أساسية رمز QR · رابط عميق على الهاتف · إشعار برقم السجل
Google ثانوية يشترط الربط الأول تحقّقًا بـ eID

ما لا وجود له: كلمات المرور، والدخول بالبريد أو برمز OTP، والدخول برمز OTP عبر الرسائل القصيرة.

وهذا قرار مقصود: كلمة المرور التي لا وجود لها لا تتسرّب، ولا يُعاد استعمالها، ولا تقع فريسةً للتصيّد.

أين تُنفِّذ المنصّة عملية الدخول — AUTH_MODE

يمكن للمنصّة في هذه المنظومة أن تؤدّي أحد دورين:

  • خدمة هوية — تُصادِق المستخدمين بنفسها. تظهر بطاقة الدخول (رمز eID الاستجابة السريعة / رقم السجل · Google) على صفحتها الرئيسية وعلى /login.
  • طرف معتمِد (RP)تُفوِّض الدخول إلى نظام دخول موحّد أعلى. عند الضغط على «تسجيل الدخول» يُحوَّل المستخدم إلى SSO، ويُصادَق هناك ثم يعود.

هذان الدوران ليسا اختلافًا في الشيفرة، بل إعداد. يحدّد ذلك إعداد AUTH_MODE في الواجهة الخلفية:

القيمة واجهة الدخول
provider تُعرض بطاقة الدخول على هذه المنصّة
client تحويل إلى نظام الدخول الموحّد الأعلى (SSO_ISSUER)

إذا لم يُضبط، يُستنتج الوضع من وجود SSO_CLIENT_ID.

تقرأ الواجهة الأمامية وضعها من نقطة النهاية العامة GET /api/v1/site/auth — دون مصادقة ودون أي أسرار في الاستجابة:

{ "mode": "client", "sso_issuer": "https://sso.gerege.mn", "provider": false }

كون المنصّة مُصدِرًا سؤال منفصل

يجيب AUTH_MODE عن سؤال «أين يسجّل مستخدمو هذه المنصّة دخولهم». أمّا كون المنصّة مُصدِرًا لتطبيقات أخرى فيحدّده OAUTH_ISSUER بشكل منفصل. ويمكن تفعيلهما معًا — ترتيب متسلسل تُصدر فيه المنصّة رموزًا للآخرين بينما تُرسل مستخدميها إلى مزوّد هوية أعلى.

النتيجة العملية: تعمل خدمة الدخول الموحّد والمنصّة التي تستهلكها على الشيفرة نفسها. تُقلَع صورة Docker ذاتها بأيّ من الدورين تبعًا لبيئتها. انظر الشيفرة المشتركة.

PIN1 مقابل PIN2

PIN1 PIN2
الشهادة Authentication Signing
الغرض الدخول التوقيع
الأثر القانوني لا يوجد موجود — عدم الإنكار

الدخول ليس توقيعًا

الدخول بـ PIN1 لا يعني أنّ المستخدم وافق على شيء. أمّا الأفعال ذات الأثر القانوني (العقود، ومنح الصلاحيات، والالتزامات المالية) فيجب أن تُوقَّع على حدة بـ PIN2.

المواصفات التقنية لـ OIDC

البند القيمة
المسار Authorization code + PKCE (S256)
Access token غير شفّاف
id_token ‏JWT بخوارزمية RS256
Refresh token متجدّد مع كشف إعادة الاستخدام
بين آلة وأخرى client_credentials
Discovery /.well-known/openid-configuration
UserInfo /userinfo

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

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

ولذلك على الجهة المعتمِدة أن تحفظ الرمز الجديد فور التحديث. فإن أبقت على القديم أسقط التحديثُ التالي جميعَ الجلسات.

الجلسة وتسجيل الخروج

  • الجلسة زوج من JWT access + refresh.
  • تسجيل الخروج يُبطل رمز التحديث ورمز الوصول معًا (قائمة منع للوصول).
  • وبعد الخروج يعود المستخدم إلى النطاق الذي بدأ منه.

خطوات أن تصير جهة معتمِدة

1. سجّل التطبيق

أنشئ عميلًا في وحدة تحكّم Gerege SSO. وستحصل على: client_id وclient_secret.

ما ينبغي تجهيزه للتسجيل:

  • عناوين redirect URI (لجميع البيئات — dev / staging / prod)
  • عنوان post-logout redirect URI
  • النطاقات (scopes) المطلوبة
  • اسم التطبيق وشعاره (سيظهران في شاشة الموافقة أمام المستخدم)

2. اقرأ ملف discovery

GET https://sso.gerege.mn/.well-known/openid-configuration

لا تكتب نقاط النهاية في الشيفرة — بل اقرأها من هنا.

3. طلب التفويض

نفّذ مسار authorization code + PKCE (S256)، واستعمل state وnonce وجوبًا.

4. بادِل الرمز

code + code_verifier ← ‏access_token وrefresh_token وid_token.

5. تحقّق من id_token

ما يجب فحصه:

  • [ ] توقيع RS256 — بالمفتاح المأخوذ من JWKS
  • [ ] تطابق iss مع المُصدِر الوارد في discovery
  • [ ] أنّ aud هو client_id الخاص بك
  • [ ] أنّ exp لم تنقضِ
  • [ ] تطابق nonce مع الذي أرسلتَه

6. بيانات المستخدم

اجلبها من نقطة النهاية /userinfo.

أخطاء شائعة

يجب تطابق redirect URI تمامًا

حرفًا بحرف: فالشرطة المائلة الأخيرة /، والفرق بين http وhttps، والمنفذ، والمسار الفرعي — كلّها مهمّة. وهذا أشيع أخطاء التكامل.

قائمة تحقّق عند تغيير النطاق

عند تغيير النطاق أو العلامة التجارية، حدِّث الأمور الثلاثة معًا. ونسيان أحدها يجعل الدخول يفشل بصمت:

  • [ ] قائمة redirect URI في الدخول الموحّد
  • [ ] حقول SAN في شهادة TLS
  • [ ] عناوين المُصدِر / نقاط النهاية في إعدادات الجهة المعتمِدة

لا تتخطَّ PKCE

يُستعمل PKCE حتى مع العملاء السرّيين. فالكلفة الإضافية زهيدة والحماية حقيقية.

نموذج الصلاحيات

بعد المصادقة يبدأ فحص الصلاحيات. والتدرّج القياسي في المنظومة:

superadmin (1) → admin (2) → manager (3) → user (4)

للتفاصيل راجع الاصطلاحات المشتركة.

على مستوى الجهة: العضوية محميّة بـ RLS في Postgres — فلا يرى المستخدم إلّا بيانات الجهة التي ينتمي إليها. وهذا قيدٌ على مستوى قاعدة البيانات، لا فحصٌ في شيفرة التطبيق.

ويستلزم منح صلاحية manager موافقةً بـ PIN2 — راجع الاصطلاحات المشتركة.