الأمن السيبراني الأدلة التقنية

ما هو الدخول الموحد SSO؟ المصطلحات التي تحتاجها أولاً

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

ما هو الدخول الموحد SSO؟ المصطلحات التي تحتاجها أولاً

لنفرض أن لديك شركة تسويق رقمي في الرياض فيها خمسة وعشرون موظفاً، وتعمل على تسعة تطبيقات: البريد، وسيرفر Git لفريق التطوير، وقاعدة المعرفة Wiki، ونظام التذاكر، والمحادثة، ولوحة المراقبة، ومجلد الملفات المشترك، ونظام علاقات العملاء CRM، ونظام الموارد البشرية. وفي كل صباح أحد يصل إلى مسؤول تقنية المعلومات طلبان أو ثلاثة لإعادة تعيين كلمة مرور، وفي الشهر الماضي غادر مصمم الشركة فأغلق المسؤول حسابه في البريد وفي المحادثة، ونسي نظام الملفات المشترك الذي بقي يفتحه من بيته أسبوعين. ثم جاء العميل الأكبر بشرط جديد في العقد: مصادقة متعددة العوامل MFA لكل من يدخل إلى بيانات العميل. والمسؤول يعرف أن تسعة تطبيقات تعني تسعة إعدادات MFA مختلفة، بعضها لا يدعمه أصلاً.

هذا هو المكان الذي يبدأ فيه الحديث عن الدخول الموحد Single Sign-On واختصاراً SSO. وعندما يفتح المسؤول أول دليل لإعداده سوف يقابل في الصفحة الأولى IdP وSP وAssertion وRedirect URI وSSO Session وMFA وSCIM، وكأن الجميع يعرفها مسبقاً. وهذا المقال هو الخريطة التي تسبق كل الأدلة الأخرى في هذا المسار: نشرح فيه كل مصطلح مرة واحدة ومن أي طرف يأتي، ونتابع شركة التسويق وهي تنتقل من تسع صفحات دخول إلى صفحة واحدة، ثم نجرب أهم فكرة فيه بأيدينا، وهي أن جلسة واحدة في مزود الهوية تفتح لك كل التطبيقات، وأن الخروج منها لا يغلق كل شيء كما يظن الناس.

وفي هذا المقال سوف نتناول:

  • لماذا لا تحل كلمة المرور الواحدة في كل مكان المشكلة، وما الفرق بين الدخول الموحد SSO وكلمة المرور الموحدة.
  • أطراف الدخول الموحد: المستخدم، ومزود الهوية IdP، ومزود الخدمة SP، والدليل Directory، وكيف تبنى الثقة بينهم.
  • الجلسات الثلاث: جلسة المزود وجلسة التطبيق والتوكنات، وهي أكثر نقطة يخطئ فيها من يبدأ.
  • تجربة عملية مع Keycloak وcurl: دخول واحد لتطبيقين، ثم تسجيل الخروج وما يبقى بعده.
  • المصادقة متعددة العوامل MFA، وتجهيز الحسابات Provisioning، والاتحاد Federation، ومخاطر وضع كل المفاتيح في مكان واحد.
  • جدول بكل المصطلحات وأين تقرأ عن كل منها بالتفصيل.

كلمة مرور لكل تطبيق، وما الذي جربته الفرق قبل SSO

لنفرض أن لديك فريقاً من عشرين شخصاً وثمانية تطبيقات مستضافة ذاتياً: البريد، وGitea، وWiki، ونظام التذاكر، والمحادثة، ومدير كلمات المرور، ولوحة المراقبة، ونظام الموارد البشرية. كل تطبيق يحفظ كلمة مرور كل موظف بطريقته، ولذلك لديك 160 كلمة مرور، وثماني صفحات دخول يمكن أن تتعرض لتخمين كلمات المرور Password Guessing، وثمانية أماكن يجب أن تغلقها في يوم مغادرة أي موظف. والحلول الأولى التي تجربها أغلب الفرق كما يلي:

  • كلمة مرور واحدة يتذكرها الموظف لكل التطبيقات: وهذا ما يحدث تلقائياً عندما تكثر كلمات المرور، والمشكلة أن تسريب كلمة المرور من أضعف تطبيق يفتح الثمانية كلها، وهذا ما يسمى حشو بيانات الدخول Credential Stuffing.
  • مدير كلمات مرور Password Manager: يحل مشكلة التذكر عند الموظف، وقد شرحناه في إدارة كلمات المرور في المؤسسة، ولكنه لا يغير شيئاً عند المؤسسة، فما زالت هناك ثمانية حسابات منفصلة وثماني سياسات وثمانية أماكن للإغلاق.
  • ربط كل التطبيقات بدليل مستخدمين Directory مثل LDAP: وهنا تصبح كلمة المرور واحدة ومخزنة في مكان واحد، وتعطيل الحساب في الدليل يمنع الدخول إلى كل التطبيقات. وهذه خطوة كبيرة، ولكن لاحظ أن كل تطبيق ما زال يعرض صفحة دخول خاصة به، ويستقبل كلمة المرور نفسها ثم يمررها إلى الدليل، فإذا اخترق أحد التطبيقات فإن المخترق يرى كلمات المرور وهي تمر من خلاله، ولا يستطيع الدليل أن يطلب عاملاً ثانياً لأنه لا يرى إلا اسم المستخدم وكلمة المرور.

والحل الأخير له اسم يخلط الناس بينه وبين SSO، وهو كلمة المرور الموحدة أو Same Sign-On: الكلمة نفسها في كل مكان، ولكنك تكتبها في كل تطبيق. أما الدخول الموحد Single Sign-On فيعني أنك تكتبها مرة واحدة فقط، في مكان واحد، ولا يراها أي تطبيق أبداً.

والصورة التالية تبين ما يعنيه ذلك بأرقام الشركة نفسها:

قبل SSO: موظف وتسعة تطبيقات هي البريد وGit وWiki والتذاكر والمحادثة والمراقبة والملفات وCRM والموارد البشرية، و25 موظفاً في 9 تطبيقات تعني 225 كلمة مرور وتسعة أماكن تغلق في يوم المغادرة، وبعد SSO: الموظف يدخل إلى مزود الهوية بكلمة مرور وMFA، والتطبيقات كلها تثق بالمزود، و25 كلمة مرور ومكان واحد للإغلاق، والتطبيق الذي لا يدعم SSO يوضع خلف Forward Auth
225 كلمة مرور وتسعة أماكن للإغلاق، مقابل صفحة دخول واحدة ومكان واحد

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

ما هو الدخول الموحد SSO؟

الدخول الموحد SSO هو أن تثبت هويتك مرة واحدة أمام طرف واحد موثوق هو مزود الهوية، ثم يقدم هذا الطرف لكل تطبيق تفتحه بعد ذلك رسالة موقعة تقول «هذه سارة، وقد تحققت منها قبل دقيقتين بكلمة المرور ورمز TOTP». والتطبيق لا يرى كلمة المرور، وإنما يتحقق من التوقيع على الرسالة ويثق بها.

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

مخطط يبين المتصفح والمستخدمة سارة يميناً ومزود الهوية في الوسط ومعه الدليل Directory، والتطبيقات wiki وgit وmail يساراً، وخمس خطوات: تفتح Wiki، فيحولها إلى المزود، فتدخل مع MFA، فيرد المزود برسالة موقعة، ثم تفتح Git فتدخل دون كلمة مرور
كلمة المرور تكتب في صفحة مزود الهوية فقط، والتطبيقات تستقبل رسالة موقعة

الأطراف والمصطلحات التي سوف تقابلها في كل دليل

الهوية Identity والدليل Directory

الهوية Identity هي سجل الشخص نفسه: اسم المستخدم، والبريد، والاسم الكامل، والمجموعات التي ينتمي إليها، وحالة الحساب نشط أو معطل. والمكان الذي تحفظ فيه هذه السجلات يسمى الدليل Directory، وقد يكون سيرفر LDAP مثل OpenLDAP أو Active Directory، وقد يكون قاعدة البيانات الداخلية لمزود الهوية نفسه. والفرق المهم هنا أن الدليل يجيب عن سؤال «من هم الموظفون؟»، أما مزود الهوية فيجيب عن سؤال «هل الذي أمامي الآن هو سارة فعلاً؟».

مزود الهوية IdP

مزود الهوية Identity Provider واختصاراً IdP هو الخدمة التي تعرض صفحة الدخول، وتتحقق من كلمة المرور والعامل الثاني، وتحفظ جلسة المستخدم، ثم تصدر الرسائل الموقعة للتطبيقات. ومن أمثلته مفتوحة المصدر authentik وKeycloak وAuthelia وZITADEL وKanidm، ومن الخدمات التجارية Microsoft Entra ID وOkta وGoogle Workspace. وفي بعض الوثائق تجد اسماً آخر لنفس الدور، فمعيار OpenID Connect يسميه OpenID Provider واختصاراً OP، ومعيار OAuth يسمي الجزء الذي يصدر التوكنات خادم التفويض Authorization Server.

مزود الخدمة SP والطرف المعتمد RP

مزود الخدمة Service Provider واختصاراً SP هو التطبيق الذي يريد أن يعرف من المستخدم، مثل Gitea أو Nextcloud أو Grafana. وهو اسم يأتي من عالم SAML، أما في OpenID Connect فاسمه الطرف المعتمد Relying Party واختصاراً RP، أي الطرف الذي يعتمد على المزود في معرفة المستخدم، وفي شاشات الإعداد تجده غالباً باسم Client أو Application. فإذا رأيت «أنشئ Client جديداً في Keycloak» أو «أضف Application في authentik» فالمقصود تسجيل التطبيق كمزود خدمة لدى المزود.

البروتوكول Protocol: SAML أم OpenID Connect؟

البروتوكول هو اللغة التي يتحدث بها التطبيق مع مزود الهوية، وفي الدخول الموحد عبر الويب ستجد اثنين فقط في الواقع:

SAML 2.0OpenID Connect
السنة2005، من منظمة OASIS2014، من OpenID Foundation فوق OAuth 2.0
شكل الرسالةوثيقة XML اسمها Assertionتوكن JSON اسمه ID Token بصيغة JWT
كيف تصلالمتصفح يرسلها في نموذج POST إلى التطبيقالتطبيق يستبدل كوداً قصيراً بالتوكنات من الخلف
أين تجده غالباًتطبيقات المؤسسات القديمة والخدمات السحابية الكبيرةالتطبيقات الحديثة والجوال وأغلب الأدوات مفتوحة المصدر

وقد شرحنا OpenID Connect بالتفصيل مع تجربة كاملة في شرح OAuth وOpenID Connect للمبتدئين، ولـ SAML دليله الخاص في هذا المسار. والقاعدة العملية: إذا دعم التطبيق الاثنين فاختر OpenID Connect، وإذا لم يدعم إلا SAML فاستخدمه دون تردد، فكل مزودي الهوية المعروفين يدعمون الاثنين.

الرسالة الموقعة: Assertion وID Token

الرسالة التي يحملها المتصفح من المزود إلى التطبيق هي قلب الدخول الموحد كله، وفي SAML اسمها Assertion، وفي OpenID Connect اسمها ID Token. وكلاهما يحمل الأشياء نفسها تقريباً: من المستخدم، ومن أصدر الرسالة Issuer، ولأي تطبيق صدرت Audience، ومتى تنتهي، ومتى تحقق المزود من المستخدم وبأي طريقة، ثم توقيع رقمي Digital Signature بمفتاح المزود الخاص. والتطبيق يرفض الرسالة إذا كان التوقيع غير صحيح، أو كانت صادرة لتطبيق آخر، أو انتهت مدتها، وهذه الفحوص الثلاثة هي ما يمنع شخصاً من أن يكتب رسالة بنفسه أو يعيد استخدام رسالة قديمة.

الثقة المسبقة: Metadata وClient ID وRedirect URI

قبل أول دخول يجب أن يعرف كل طرف الآخر، وهذه الخطوة هي ما تفعله في شاشات الإعداد:

  • في SAML: يتبادل الطرفان ملفين بصيغة XML اسمهما Metadata، وفي ملف المزود عنوان الدخول SSO URL وشهادة التوقيع، وفي ملف التطبيق معرفه Entity ID وعنوان استقبال الرسائل Assertion Consumer Service واختصاراً ACS.
  • في OpenID Connect: تسجل التطبيق عند المزود فيعطيك معرف التطبيق Client ID وسره Client Secret، وتسجل عنده عنوان العودة Redirect URI الذي يقبل المزود أن يرسل إليه الكود، والتطبيق يقرأ كل شيء آخر من عنوان الاكتشاف Discovery الذي ينتهي بـ /.well-known/openid-configuration.

من يبدأ الدخول: SP-initiated أم IdP-initiated؟

في الطريقة المعتادة يفتح المستخدم التطبيق أولاً، فيحوله التطبيق إلى المزود، وهذا ما يسمى الدخول الذي يبدؤه التطبيق SP-initiated. وفي الطريقة الثانية يفتح المستخدم لوحة المزود التي تعرض أيقونات التطبيقات ثم يضغط على أحدها، فيرسل المزود رسالة لم يطلبها التطبيق، وهذا ما يسمى IdP-initiated، وهو موجود في SAML فقط. ولاحظ أن الطريقة الثانية أضعف، والسبب أن التطبيق يستقبل رسالة لم يطلبها، فلا يستطيع أن يربطها بطلب خرج من عنده، ولذلك تفضل أغلب الأدلة أن تجعل أيقونات اللوحة روابط تفتح التطبيق، والتطبيق هو الذي يبدأ الدخول.

الجلسات Sessions: ثلاث جلسات وليست جلسة واحدة

هذه هي النقطة التي يخطئ فيها أغلب من يبدأ، والسبب أن كلمة «الجلسة» تستخدم لثلاثة أشياء مختلفة. وإذا لم تكن تعرف كيف يتذكر الموقع المستخدم أصلاً عبر ملفات تعريف الارتباط Cookies فابدأ بـ شرح الجلسات وCookies وJWT، ثم عد إلى هنا:

  1. جلسة المزود SSO Session: ملف تعريف ارتباط على نطاق مزود الهوية، يتذكر به المزود أنك دخلت قبل قليل، وهي التي تجعل التطبيق الثاني يدخل دون أن تكتب كلمة المرور.
  2. جلسة التطبيق App Session: بعد أن يستقبل التطبيق الرسالة الموقعة ينشئ جلسته الخاصة في ملف تعريف ارتباط على نطاقه، ومن تلك اللحظة لا يسأل المزود عن شيء حتى تنتهي جلسته.
  3. التوكنات Tokens: في OpenID Connect يحصل التطبيق أيضاً على Access Token قصير العمر وRefresh Token يجدده به، والتجديد يمر على المزود في كل مرة.
مخطط من ثلاثة أعمدة: جلسة المزود KEYCLOAK_SESSION تنتهي عند الخروج من المزود، وجلسة التطبيق wiki_session تبقى حتى تنتهي مدتها أو يصلها Back-channel Logout، والتوكنات حيث يعمل Access Token حتى وقت exp ويرفض Refresh Token فوراً برسالة Session not active
الخروج من المزود ينهي جلسة المزود، أما جلسات التطبيقات فلكل منها عمرها الخاص

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

كم يجب أن تعيش كل جلسة؟

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

  • مهلة عدم النشاط Idle Timeout: تنتهي الجلسة إذا لم يستخدمها صاحبها هذه المدة، فإذا ترك الموظف جهازه مفتوحاً وغادر المكتب لا تبقى جلسته صالحة طوال اليوم.
  • الحد الأقصى Max Lifespan: تنتهي الجلسة بعد هذه المدة مهما كان النشاط، والقيمة الافتراضية في Keycloak عشر ساعات، وهو ما رأيناه في التجربة كقيمة Max-Age=36000 في ملف تعريف الارتباط.

وهذا مثال لقرار الشركة، تبدأ منه وتعدله بحسب عملك:

الجلسةالمدة المقترحةالسبب
جلسة المزود للموظفينيوم عمل، مع مهلة عدم نشاط قصيرةيدخل الموظف صباحاً مرة، وتنتهي جلسته إذا ترك جهازه
جلسة المزود للمديرينساعات قليلة، وإعادة مصادقة للعمليات الحساسةجلسة المدير المسروقة تفتح لوحة المزود نفسها
جلسة التطبيقأقصر من جلسة المزود، أو بحسب دعم Back-Channel Logoutهي المدة التي يبقى فيها المغادر داخل التطبيق بعد تعطيله
Access Tokenدقائقيتحقق منه التطبيق محلياً دون أن يسأل المزود
Refresh Tokenبطول جلسة المزودكل تجديد يمر على المزود فيعرف إن انتهت الجلسة

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

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

سوف نشغل Keycloak كمزود هوية، وننشئ فيه مستخدمة اسمها sara وتطبيقين اسمهما wiki وgit، ثم نستخدم curl مع ملف لحفظ ملفات تعريف الارتباط Cookie Jar ليقوم بدور المتصفح، حتى نرى كل تحويل وكل ملف تعريف ارتباط كما هو. ولا نحتاج إلى تطبيقين حقيقيين، لأن ما يهمنا هو ما يرسله المزود إلى عنوان العودة، وcurl يرينا هذا العنوان دون أن يتبعه.

الخطوة 1: تشغيل Keycloak وإنشاء المستخدمة والتطبيقين

نشغل Keycloak بوضع التطوير start-dev الذي يحفظ بياناته في قاعدة H2 داخلية، وهو مناسب للتجربة فقط وغير مناسب إطلاقاً للإنتاج:

docker run -d --name sso-lab-kc -p 8080:8080 \
  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
  -e KC_BOOTSTRAP_ADMIN_PASSWORD='change-me-admin' \
  quay.io/keycloak/keycloak:26.8.1 start-dev

بعد أن يظهر في السجلات السطر Keycloak 26.8.1 on JVM … started ننشئ عالماً Realm باسم demo، وهو الحاوية المنطقية التي تضم المستخدمين والتطبيقات في Keycloak، ثم المستخدمة والتطبيقين عبر أداة الإدارة kcadm.sh:

K="docker exec sso-lab-kc /opt/keycloak/bin/kcadm.sh"
$K config credentials --server http://localhost:8080 --realm master --user admin --password 'change-me-admin'
$K create realms -s realm=demo -s enabled=true
$K create users -r demo -s username=sara -s [email protected] -s firstName=Sara -s lastName=Ali -s emailVerified=true -s enabled=true
$K set-password -r demo --username sara --new-password 'Sara-Lab-2026'
$K create clients -r demo -s clientId=wiki -s secret=wiki-secret-lab -s 'redirectUris=["http://localhost:18801/callback"]' -s publicClient=false -s standardFlowEnabled=true
$K create clients -r demo -s clientId=git -s secret=git-secret-lab -s 'redirectUris=["http://localhost:18802/callback"]' -s publicClient=false -s standardFlowEnabled=true

في الإعداد أعلاه لاحظ التالي:

  • كل تطبيق له Client ID وسر Client Secret وعنوان عودة واحد مسموح به، وهذه هي الثقة المسبقة التي ذكرناها.
  • العنوانان 18801 و18802 لا يعمل عليهما أي شيء، فنحن نريد أن نقرأ ما يرسله المزود إليهما فقط.
  • إذا كنت تستخدم Git Bash على Windows فاكتب قبل الأوامر export MSYS_NO_PATHCONV=1، حتى لا يحول المسار /opt/keycloak/… إلى مسار Windows.

الخطوة 2: Wiki يحولنا إلى المزود، وسارة تدخل مرة واحدة

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

IDP=http://localhost:8080/realms/demo/protocol/openid-connect
curl -s -c jar.txt -b jar.txt "$IDP/auth?client_id=wiki&response_type=code&scope=openid&redirect_uri=http://localhost:18801/callback&state=w1" -o form.html -w 'HTTP %{http_code}, login form: %{size_download} bytes\n'
ACTION=$(grep -o 'action="[^"]*"' form.html | head -1 | sed 's/action="//;s/"$//;s/&/\&/g')
curl -s -c jar.txt -b jar.txt -D h1.txt -o /dev/null --data-urlencode username=sara --data-urlencode password='Sara-Lab-2026' "$ACTION"
grep -iE '^(HTTP|location)' h1.txt | cut -c1-110
grep -io 'set-cookie: [A-Z_]*=' h1.txt

والمخرج سوف يكون كما يلي:

HTTP 200, login form: 6766 bytes
HTTP/1.1 302 Found
Location: http://localhost:18801/callback?state=w1&session_state=XpKFqAsv6Khdnd9qCTd7Qlw2&iss=http%3A%2F%2Floc
Set-Cookie: KC_RESTART=
Set-Cookie: KEYCLOAK_IDENTITY=
Set-Cookie: KEYCLOAK_SESSION=

لاحظ أن المزود أعاد المتصفح إلى عنوان Wiki ومعه كود قصير العمر وقيمة session_state، ووضع في المتصفح ملفين مهمين: KEYCLOAK_IDENTITY وKEYCLOAK_SESSION. وهذان الملفان هما جلسة المزود، وفي ردنا الحقيقي كانت مدة KEYCLOAK_SESSION هي Max-Age=36000، أي عشر ساعات، وهي القيمة الافتراضية للحد الأقصى لجلسة SSO في Keycloak كما يوضح قسم المهلات Timeouts في دليل الإدارة.

الخطوة 3: Git يحولنا إلى المزود نفسه، فلا تظهر صفحة الدخول

الآن تفتح سارة تطبيق Git، فيحولها هو الآخر إلى المزود بمعرفه وعنوان عودته. ونستخدم ملف ملفات تعريف الارتباط نفسه، تماماً كما يفعل المتصفح:

curl -s -c jar.txt -b jar.txt -D h2.txt -o /dev/null "$IDP/auth?client_id=git&response_type=code&scope=openid&redirect_uri=http://localhost:18802/callback&state=g1"
grep -iE '^(HTTP|location)' h2.txt | cut -c1-110
HTTP/1.1 302 Found
Location: http://localhost:18802/callback?state=g1&session_state=XpKFqAsv6Khdnd9qCTd7Qlw2&iss=http%3A%2F%2Floc

وهذا هو الدخول الموحد كله في سطرين: لم يرد المزود بصفحة دخول (الرمز 200 في الخطوة السابقة)، وإنما رد مباشرة بالتحويل 302 إلى تطبيق Git ومعه كود جديد، لأنه وجد ملف KEYCLOAK_SESSION فعرف أن سارة دخلت قبل ثانيتين. ولاحظ أن session_state هي نفسها في الردين، أي أن التطبيقين يعتمدان على جلسة المزود نفسها.

الخطوة 4: كل تطبيق يستبدل كوده بالتوكنات

الكود وحده لا يعني شيئاً، فكل تطبيق يرسله من الخلف إلى المزود مع سره، ويحصل على التوكنات. ونفعل ذلك للتطبيقين ثم نقرأ أهم حقول الـ ID Token:

code_of() { grep -i '^location' "$1" | sed 's/.*[?&]code=\([^&\r]*\).*/\1/' | tr -d '\r'; }
b64d() { local s=$(echo -n "$1" | tr '_-' '/+'); while [ $(( ${#s} % 4 )) -ne 0 ]; do s="$s="; done; echo -n "$s" | base64 -d 2>/dev/null; }
for app in wiki:18801 git:18802; do n=${app%%:*}; p=${app##*:}; f=h1.txt; [ $n = git ] && f=h2.txt
  curl -s "$IDP/token" -d grant_type=authorization_code -d client_id=$n -d client_secret=$n-secret-lab \
    -d code=$(code_of $f) -d redirect_uri=http://localhost:$p/callback > tok-$n.json
  idt=$(grep -o '"id_token":"[^"]*"' tok-$n.json | cut -d'"' -f4)
  echo "-- $n id_token:"; b64d "$(echo $idt | cut -d. -f2)" | tr ',' '\n' | grep -E '"(aud|sub|auth_time|sid|preferred_username|iat|exp)"'
done
-- wiki id_token:
{"exp":1792955612
"iat":1792955312
"auth_time":1792955311
"aud":"wiki"
"sub":"ef3c77b7-31e8-499b-867f-f83d325d95bc"
"sid":"XpKFqAsv6Khdnd9qCTd7Qlw2"
"preferred_username":"sara"
-- git id_token:
{"exp":1792955613
"iat":1792955313
"auth_time":1792955311
"aud":"git"
"sub":"ef3c77b7-31e8-499b-867f-f83d325d95bc"
"sid":"XpKFqAsv6Khdnd9qCTd7Qlw2"
"preferred_username":"sara"

في المخرج أعلاه لاحظ التالي:

  • aud مختلف في كل توكن، فتوكن Wiki صادر لـ Wiki فقط، وإذا حاول أحد أن يقدمه إلى Git فيجب أن يرفضه Git، وهذا هو فحص الجمهور Audience الذي ذكرناه.
  • sub واحد في التوكنين، وهو المعرف الثابت للمستخدمة، وعلى التطبيق أن يربط حسابه به وليس بالبريد أو الاسم، لأن البريد قد يتغير.
  • auth_time واحد في التوكنين (1792955311)، فهو وقت إدخال كلمة المرور الفعلي وليس وقت إصدار التوكن، ولذلك يستطيع التطبيق الحساس أن يقرر أن دخولاً قديماً لا يكفيه.
  • sid هو معرف جلسة المزود، وهو نفسه في التوكنين، وسوف يستخدمه المزود لاحقاً ليخبر كل تطبيق بأن هذه الجلسة انتهت.
  • الفرق بين exp وiat هو 300 ثانية، أي أن مدة الـ ID Token والـ Access Token هنا خمس دقائق، وهي القيمة الافتراضية في Keycloak.

ومن جهة المزود نرى الجلسة نفسها عبر واجهة الإدارة REST، وفيها التطبيقان:

$K get users/ef3c77b7-31e8-499b-867f-f83d325d95bc/sessions -r demo
[ {
  "id" : "XpKFqAsv6Khdnd9qCTd7Qlw2",
  "username" : "sara",
  "userId" : "ef3c77b7-31e8-499b-867f-f83d325d95bc",
  "ipAddress" : "192.168.96.1",
  "start" : 1792955310000,
  "lastAccess" : 1792955313000,
  "rememberMe" : false,
  "clients" : {
    "dc672ad6-6ab8-46a7-bc89-e5cff58e5470" : "git",
    "78971e96-ba1c-4928-bfae-90793fbab54b" : "wiki"
  },
  "transientUser" : false
} ]

والصورة التالية من شاشة Sessions في لوحة إدارة Keycloak، وفيها الجلسة نفسها ومعها التطبيقان:

شاشة Sessions في لوحة إدارة Keycloak للعالم demo، وفيها جلسة واحدة من نوع REGULAR للمستخدمة sara، وفي عمود Clients التطبيقان git وwiki
جلسة واحدة في المزود، وتحتها كل التطبيقات التي دخلتها سارة بها

الخطوة 5: نخرج من Wiki، فماذا يحدث لـ Git؟

الآن تخرج سارة من Wiki، والتطبيق يرسل طلب الخروج إلى المزود من الخلف بالـ Refresh Token الذي معه، فينهي المزود الجلسة كلها. بعد ذلك نسأل ثلاثة أسئلة من جهة Git: هل يستطيع أن يجدد توكنه؟ وماذا يقول المزود عن الـ Access Token الذي معه؟ وماذا يحدث إذا فتحت سارة Git مرة أخرى؟

RT=$(grep -o '"refresh_token":"[^"]*"' tok-wiki.json | cut -d'"' -f4)
curl -s -o /dev/null -w 'HTTP %{http_code}\n' "$IDP/logout" -d client_id=wiki -d client_secret=wiki-secret-lab -d refresh_token=$RT

RT2=$(grep -o '"refresh_token":"[^"]*"' tok-git.json | cut -d'"' -f4)
curl -s "$IDP/token" -d grant_type=refresh_token -d client_id=git -d client_secret=git-secret-lab -d refresh_token=$RT2; echo

AT2=$(grep -o '"access_token":"[^"]*"' tok-git.json | cut -d'"' -f4)
curl -s "$IDP/token/introspect" -d client_id=git -d client_secret=git-secret-lab -d token=$AT2; echo

curl -s -c jar.txt -b jar.txt -o /dev/null -w 'HTTP %{http_code}\n' "$IDP/auth?client_id=git&response_type=code&scope=openid&redirect_uri=http://localhost:18802/callback&state=g2"

والمخرج سوف يكون كما يلي:

HTTP 204
{"error":"invalid_grant","error_description":"Session not active"}
{"active":false}
HTTP 200

في المخرج أعلاه لاحظ التالي:

  • الرد 204 يعني أن المزود أنهى الجلسة، ولم يعد في المتصفح ما يفتح التطبيقات تلقائياً، فالطلب الأخير من Git رجع بصفحة الدخول (الرمز 200) بدلاً من التحويل 302.
  • تجديد التوكن في Git فشل برسالة Session not active، لأن التجديد يمر على المزود دائماً.
  • عندما سأل Git المزود عن الـ Access Token عبر نقطة الفحص Introspection المعرفة في RFC 7662 كان الرد "active":false. ولكن لاحظ أن أغلب التطبيقات لا تسأل المزود أصلاً، وإنما تتحقق من توقيع الـ JWT ومن exp بنفسها، وفي تجربتنا كان exp لتوكن Git هو 1792955613 ووقت الخروج 1792955427، أي أن التطبيق الذي يتحقق محلياً سوف يقبل التوكن ثلاث دقائق أخرى بعد الخروج.
  • والأهم من ذلك جلسة التطبيق نفسه: لو كان Git تطبيقاً حقيقياً لكان قد أنشأ جلسته الخاصة عند الدخول، وهذه الجلسة لا يعرف بها المزود، فتبقى مفتوحة حتى تنتهي مدتها، إلا إذا كان التطبيق يدعم إشعار الخروج من الخلف الذي نشرحه الآن.

الخروج الموحد Single Logout: لماذا هو أصعب من الدخول؟

الدخول الموحد سهل لأن المتصفح يمر على المزود في كل دخول، أما الخروج فيحتاج المزود أن يخبر كل تطبيق فتحت فيه جلسة، وهذا ما يسمى الخروج الموحد Single Logout واختصاراً SLO. وفي OpenID Connect ثلاثة معايير لذلك:

  • RP-Initiated Logout: التطبيق يحول المستخدم إلى عنوان الخروج في المزود، وهذا ينهي جلسة المزود فقط.
  • Front-Channel Logout: المزود يفتح في المتصفح صفحة خروج كل تطبيق في إطارات مخفية iframes، وهذه الطريقة تفشل كثيراً اليوم لأن المتصفحات تحجب ملفات تعريف الارتباط داخل الإطارات القادمة من نطاق آخر.
  • Back-Channel Logout: المزود يرسل من سيرفره إلى سيرفر كل تطبيق رسالة موقعة اسمها Logout Token تحمل sid، فينهي التطبيق الجلسة المرتبطة بها، وهي الطريقة الموثوقة لأنها لا تعتمد على المتصفح.

وفي SAML يوجد Single Logout أيضاً، ولكن دعمه في التطبيقات أضعف بكثير. لذلك عند اختيار تطبيق للمؤسسة اسأل: هل يدعم Back-Channel Logout؟ وإذا لم يدعمه فاجعل مدة جلسته قصيرة، ساعات وليس أسابيع، والسبب أن مدة جلسة التطبيق هي المدة التي يبقى فيها الموظف المغادر داخل التطبيق بعد أن تعطله في المزود.

والصورة التالية تجمع الطرق الثلاث، ومن يخبر من في كل طريقة:

ثلاث طرق للخروج: RP-Initiated حيث يحول التطبيق المتصفح إلى /logout فتنتهي جلسة المزود والتطبيقات الأخرى لا تعرف، وFront-Channel حيث يزور المتصفح كل تطبيق في iframe ويفشل عندما يحجب المتصفح ملفات الطرف الثالث، وBack-Channel حيث يرسل سيرفر المزود Logout Token يحمل sid عبر POST إلى wiki وgit وmail ولا يعتمد على المتصفح ولكن يحتاج تطبيقاً يدعمه
الطريقة الموثوقة هي التي لا تعتمد على المتصفح، وهي Back-Channel

وفي شركة التسويق كان السؤال العملي: أي التطبيقات التسعة تدعم Back-Channel Logout؟ والإجابة تجدها في توثيق كل تطبيق، وغالباً تكون قلة منها، لذلك الأنسب أن تكون جلسات التطبيقات الحساسة، مثل CRM ونظام الموارد البشرية، قصيرة لا تتجاوز ساعات، وأن تكون المغادرة إجراء يغلق الحساب في المزود ثم يعطله في التطبيقات التي تحمل بيانات العملاء، كما شرحنا في مقال SCIM.

المصادقة متعددة العوامل MFA: مكانها في المزود

من أكبر فوائد الدخول الموحد أن المصادقة متعددة العوامل Multi-Factor Authentication واختصاراً MFA تفرض في مكان واحد، فبدلاً من أن تبحث هل يدعم كل تطبيق رموز TOTP، تفرضها في المزود فتصبح كل التطبيقات محمية بها. وقد شرحنا فرضها في دليل تثبيت authentik، والطريقة الأقوى ضد التصيد Phishing هي مفاتيح المرور Passkeys. وهناك ثلاثة مصطلحات مرتبطة سوف تقابلها:

  • مستوى المصادقة acr وطرقها amr: حقلان في الـ ID Token يخبران التطبيق كيف تحقق المزود من المستخدم، فـ amr يحمل قيماً مثل pwd وotp وhwk المعرفة في RFC 8176، وacr يحمل اسم المستوى الذي يتفق عليه الطرفان.
  • رفع مستوى المصادقة Step-up Authentication: التطبيق يقبل الدخول بكلمة المرور لقراءة الصفحات، ولكنه يطلب من المزود مستوى أعلى قبل عملية حساسة مثل تحويل مالي، وقد وحد معيار RFC 9470 طريقة طلب ذلك.
  • إعادة المصادقة Re-authentication: التطبيق يرسل max_age أو prompt=login فيطلب المزود كلمة المرور من جديد حتى لو كانت جلسته مفتوحة، ويتأكد التطبيق من ذلك عبر auth_time الذي رأيناه في التجربة.

وفي السعودية، إذا كانت جهتك ضمن نطاق الضوابط الأساسية للأمن السيبراني ECC فإن الضابط 2-2-3-2 في وثيقة ECC-2:2024 يطلب التحقق متعدد العوامل للدخول عن بعد Remote Access وللحسابات ذات الصلاحيات الهامة Privileged Accounts، مع تحديد العوامل وعددها بحسب تقييم أثر فشل المصادقة أو تجاوزها، كما في النسخة الإنجليزية. والدخول الموحد هو أسهل طريقة لتحقيق ذلك، لأنك تفرضه مرة واحدة في المزود ثم تثبت للمدقق أن كل تطبيق يمر عليه.

تجهيز الحسابات Provisioning: الدخول شيء، والحساب شيء آخر

الدخول الموحد يجيب عن «من يدخل الآن؟»، ولكن الحساب نفسه يعيش داخل كل تطبيق، ومعه مجموعاته وملفاته ورموزه Tokens. وهناك ثلاث طرق لوصول الحساب إلى التطبيق:

الطريقةكيف تعملما ينقصها
الإنشاء عند أول دخول JITالتطبيق ينشئ الحساب عندما تصله أول رسالة موقعة عن المستخدملا يعطل الحساب عند المغادرة، لأن من غادر لن يدخل مرة أخرى
المزامنة من الدليل LDAP Syncالتطبيق يسحب المستخدمين والمجموعات من LDAP دورياًالتغيير يصل في المزامنة التالية، وبعض التطبيقات لا تعطل من حذف
SCIMالمزود يرسل الإنشاء والتعديل والتعطيل إلى التطبيق فور حدوثهأغلب التطبيقات مفتوحة المصدر لا تدعمه بعد

وقد خصصنا لهذه الفجوة مقالاً كاملاً مع تجربة عملية في ما هو SCIM؟، ولدورة حياة الحساب من التعيين إلى المغادرة مقال دورة حياة حساب الموظف JML.

الاتحاد Federation والوسيط Identity Brokering

الاتحاد Federation هو أن يثق مزود هوية بمزود هوية آخر. فإذا كانت شركتك تعمل مع جهة شريكة لها مزود هويتها الخاص، فبدلاً من أن تنشئ حسابات لموظفيها عندك، تربط مزودك بمزودهم، فيدخل موظفوهم بحساباتهم ويصلك منهم الاسم والبريد فقط. ومن الحالات الشائعة أيضاً الدخول بحساب Google أو Microsoft، وهنا يقوم مزودك بدور الوسيط Identity Broker: يحول المستخدم إلى Google، ثم يستقبل الرد ويصدر رسالته الخاصة لتطبيقاتك، فتبقى التطبيقات مربوطة بمزود واحد هو مزودك. وقد طبقنا ذلك في تسجيل الدخول بحساب Google في authentik.

متعاقد من وكالة شريكة يملك حساب Google فقط، يدخل عبر مزودك authentik الذي يقبل الدخول من Google ثم يصدر رسالته هو ويطبق مجموعاته وMFA، والتطبيقات Wiki وGit والتذاكر والملفات تستقبل رسالة من مزودك فقط، ولماذا لا تربط التطبيقات بـ Google مباشرة: لأن المجموعات والصلاحيات تبقى عندك وتغلق المتعاقد من مكان واحد وتستبدل Google دون أن تلمس التطبيقات، والاتحاد Federation نفس الفكرة بين مؤسستين
التطبيقات لا تعرف Google، وإنما تعرف مزودك فقط

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

كل المفاتيح في مكان واحد: مخاطر الدخول الموحد

الدخول الموحد يقلل عدد الأبواب، ولكنه يجعل باباً واحداً أهم من كل الأبواب، ولذلك عامل مزود الهوية كأنه أهم سيرفر عندك:

  • جلسة المزود تساوي كل التطبيقات: من سرق ملف تعريف الارتباط الخاص بجلسة المزود دخل كل التطبيقات دون كلمة مرور ودون MFA، لأن المصادقة قد حدثت مسبقاً. لذلك اجعل مدة جلسة المزود معقولة، وأعد طلب المصادقة للعمليات الحساسة.
  • حسابات مديري المزود: مدير المزود يستطيع أن ينشئ مستخدماً بأي مجموعة، أو يضيف نفسه إلى مجموعة المديرين في كل تطبيق. لذلك افرض على مديري المزود أقوى عامل ثاني عندك، ويفضل مفاتيح الأمان Security Keys.
  • توقف المزود يوقف الجميع: إذا توقف المزود فلا أحد يدخل أي تطبيق، وهذا يشمل فريق تقنية المعلومات الذي يريد أن يصلحه. لذلك تحتاج إلى نسخ احتياطي للمزود، وإلى حساب طوارئ Break-glass لا يعتمد عليه.
📌
في أكتوبر 2023 أعلنت Okta، وهي من أكبر مزودي الهوية التجاريين، أن مهاجماً دخل نظام الدعم الفني لديها بين 28 سبتمبر و17 أكتوبر 2023 عبر حساب خدمة Service Account كانت بياناته محفوظة في حساب Google شخصي لأحد الموظفين، فنزل ملفات من 134 عميلاً، بعضها ملفات HAR التي يسجل فيها المتصفح الطلبات ومعها توكنات الجلسات Session Tokens، واستخدمها ليختطف جلسات حقيقية لخمسة عملاء. ومن الإصلاحات التي أعلنتها الشركة في تقرير السبب الجذري ربط جلسة المدير بموقع الشبكة، فإذا تغير الموقع طلبت المصادقة من جديد. والدرس هنا أن الجلسة المسروقة لا تحتاج إلى كلمة المرور ولا إلى MFA، فاحم ملفات الجلسات كما تحمي كلمات المرور، ولا ترسل ملف HAR لأحد قبل أن تحذف منه ملفات تعريف الارتباط والتوكنات.

ماذا يحدث عندما يتوقف مزود الهوية؟

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

  • جلسات التطبيقات المفتوحة تستمر: من فتح البريد صباحاً يبقى يعمل حتى تنتهي جلسة التطبيق، لأن التطبيق لا يسأل المزود عن كل طلب.
  • التجديد يفشل: التطبيقات التي تجدد التوكنات كل بضع دقائق تخرج مستخدميها بعد أول تجديد، كما فشل تجديد Git في الخطوة 5 برسالة Session not active، وهذا ما يجعل التوقف يظهر بالتدريج.
  • الدخول الجديد مستحيل: كل من أغلق متصفحه أو فتح تطبيقاً جديداً يتوقف عند صفحة خطأ.

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

كيف تنتقل الشركة إلى SSO خطوة خطوة؟

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

  1. الجرد: جدول بالتطبيقات، وما يدعمه كل منها: OpenID Connect أم SAML أم LDAP فقط أم لا شيء، ومن يملك كل تطبيق، وما البيانات الحساسة فيه. وفي شركة كهذه تجد عادة أغلب التطبيقات الحديثة تدعم OIDC، وبعض الخدمات القديمة SAML فقط، وتطبيقاً أو اثنين يدعمان LDAP، ولوحة قديمة لا تدعم شيئاً.
  2. المزود أولاً: تثبيت مزود الهوية، ونقل المستخدمين إليه، وفرض MFA على الجميع قبل ربط أي تطبيق، حتى يتعود الموظفون على صفحة الدخول الجديدة والعامل الثاني.
  3. تطبيق تجريبي: قاعدة المعرفة Wiki أولاً، لأن توقفها لساعة لا يوقف العمل، ويستخدمها الجميع فتظهر المشكلات بسرعة.
  4. التطبيقات الحساسة: البريد ونظام الملفات وCRM، مع مدة جلسة قصيرة في كل منها، لأنها التي يطلب العميل حمايتها.
  5. التطبيقات القديمة: التطبيق الذي يدعم LDAP فقط يقرأ المستخدمين عبر LDAP، واللوحة التي لا تدعم شيئاً توضع خلف صفحة دخول المزود عبر Forward Auth.
  6. إغلاق الأبواب القديمة: بعد أن يعمل الدخول الموحد في كل تطبيق، تعطل كلمات المرور المحلية فيه، إلا حساب مدير طوارئ واحد، حتى لا يبقى طريق جانبي يتجاوز MFA.

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

أخطاء شائعة

الخطألماذا يهم
تعطيل الحساب في المزود فقطجلسات التطبيقات والرموز Tokens تبقى، كما رأينا في التجربة
جلسة تطبيق ثلاثين يوماًالمزود يقرر الدخول الأول فقط
ترك الدخول بكلمة المرور المحلية مفعلاًباب جانبي يتجاوز MFA
ربط الحساب في التطبيق بالبريد بدلاً من subالبريد يتغير أو يعاد استخدامه لموظف جديد
Redirect URI عامة بنجمةالمزود قد يرسل الكود إلى عنوان لا تملكه
لوحة المزود خلف المزود دون حساب طوارئلا أحد يدخل لإصلاحه عندما يتوقف

وكل خطأ في الجدول له مثال في مكان ما من هذا المقال، فإذا كنت تراجع إعداداً موجوداً فابدأ بهذه الأسئلة الستة قبل أي شيء آخر.

جدول المصطلحات

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

المصطلحمعناه باختصار
الدخول الموحد SSOتثبت هويتك مرة واحدة أمام مزود الهوية، فتفتح كل التطبيقات المربوطة به
كلمة المرور الموحدة Same Sign-Onكلمة المرور نفسها من الدليل، ولكنك تكتبها في كل تطبيق
مزود الهوية IdP أو OPالخدمة التي تتحقق من المستخدم وتصدر الرسائل الموقعة
مزود الخدمة SP أو RP أو Clientالتطبيق الذي يثق بمزود الهوية
الدليل Directoryمخزن المستخدمين والمجموعات، مثل LDAP
Assertionرسالة SAML الموقعة بصيغة XML
ID Tokenرسالة OpenID Connect الموقعة بصيغة JWT
Metadata وEntity ID وACSبيانات الثقة المسبقة في SAML
Client ID وClient Secret وRedirect URIبيانات الثقة المسبقة في OpenID Connect
جلسة المزود SSO Sessionما يجعل التطبيق الثاني يدخل دون كلمة مرور
جلسة التطبيق App Sessionجلسة كل تطبيق الخاصة بعد أن يستقبل الرسالة
الخروج الموحد SLOإنهاء الجلسة في المزود وفي كل التطبيقات، والموثوق منه Back-Channel Logout
المصادقة متعددة العوامل MFAعامل ثاني بعد كلمة المرور، يفرض مرة واحدة في المزود
acr وamrحقول تخبر التطبيق بمستوى المصادقة وطريقتها
JIT Provisioningإنشاء الحساب في التطبيق عند أول دخول
SCIMمعيار يرسل به المزود إنشاء الحسابات وتعطيلها إلى التطبيقات
الاتحاد Federation والوسيط Brokerمزود يثق بمزود آخر، مثل الدخول بحساب Google

من أين تبدأ؟

إذا كنت تبدأ من الصفر وتريد مزود هوية لفريق صغير أو متوسط فابدأ بـ authentik، فقد شرحنا تثبيته وربطه بالتطبيقات خطوة خطوة، وإذا كانت تطبيقاتك لا تدعم OIDC ولا SAML فضع أمامها صفحة دخول المزود عبر Forward Auth. والمقالات التالية تكمل هذه الخريطة:

دليلتثبيت authentik للدخول الموحد SSO إلى تطبيقاتككيف تثبت authentik حتى يدخل كل موظف إلى تطبيقات الفريق بحساب واحد، مع فرض المصادقة الثنائية على الجميع.دليلكيف تحمي أي تطبيق ويب بصفحة دخول authentik عبر Forward Authكيف تضع صفحة دخول authentik مع المصادقة الثنائية أمام أي أداة داخلية دون أن تعدل في التطبيق نفسه.دليلشرح OAuth وOpenID Connect للمبتدئينلماذا لا يجب أن يعرف أي تطبيق كلمة مرورك، وكيف يحل OAuth ذلك بتوكنات محدودة، وكيف يضيف OpenID Connect الدخول الموحد.دليلSAML للمبتدئين: متى ما زالت المؤسسات تحتاجه؟نشرح SAML بتجربة حقيقية نرى فيها الـ Assertion كما يحمله المتصفح، ثم نعدله ونسرقه ونؤخره لنرى كيف يرفضه التطبيق.دليلما هو SCIM؟ إدارة حسابات الموظفين تلقائياً في كل تطبيقاتكالدخول الموحد SSO يمنع الموظف المغادر من الدخول لكن حساباته تبقى نشطة، وSCIM ينشئ الحسابات ويعطلها في كل تطبيق تلقائياً.دليلLDAP ودليل المستخدمين: كيف تعرف التطبيقات من هو المستخدم؟نبني دليل مستخدمين على OpenLDAP ونرى بمخرجات ldapsearch الحقيقية كيف تتحقق التطبيقات من كلمة المرور والمجموعات، وأين يخطئ أغلب من يبدأ.دليلالدخول دون كلمة مرور: شرح Passkeys وWebAuthnلماذا لا تحميك رموز SMS وTOTP من التصيد الحديث، وكيف تحل Passkeys المشكلة بمفتاح خاص لا يغادر جهازك.دليلإدارة الهوية والوصول IAM والوصول المميز PAMمن يملك صلاحية root على سيرفراتك ومنذ متى، وكيف تضبط حسابات المديرين بصلاحيات مؤقتة وجلسات مسجلة.

الخلاصة

  • الدخول الموحد SSO يعني أن كلمة المرور تكتب في صفحة مزود الهوية فقط، والتطبيقات تستقبل رسالة موقعة، وهذا يختلف عن كلمة المرور الموحدة من LDAP التي تكتبها في كل تطبيق.
  • الأطراف أربعة: المستخدم ومتصفحه، ومزود الهوية IdP، والتطبيقات SP أو RP، والدليل Directory خلف المزود. والثقة بينهم تبنى مسبقاً بالـ Metadata في SAML أو Client ID وRedirect URI في OIDC.
  • هناك ثلاث جلسات: جلسة المزود التي تفتح التطبيقات دون كلمة مرور، وجلسة كل تطبيق، والتوكنات. وفي تجربتنا مع Keycloak 26.8.1 فتحت جلسة واحدة تطبيقين بنفس sid، وبعد الخروج رفض المزود تجديد التوكن فوراً، بينما بقي الـ Access Token صالحاً محلياً حتى exp.
  • الخروج الموحد الموثوق هو Back-Channel Logout، وإذا لم يدعمه التطبيق فاجعل مدة جلسته قصيرة.
  • افرض MFA مرة واحدة في المزود، والحسابات داخل التطبيقات تحتاج إلى SCIM أو مزامنة من الدليل حتى تغلق عند المغادرة.
  • مزود الهوية أهم سيرفر عندك: احم جلساته ومديريه، وجهز نسخه الاحتياطي وحساب الطوارئ قبل أن تحتاجهما.

سجل التحديثات

  • أكتوبر 2026: كتابة المقال، وتنفيذ تجربة الجلسة الواحدة لتطبيقين على Keycloak 26.8.1.
  • أكتوبر 2026: توسيع المقال بقصة شركة التسويق، وأقسام عن مدة الجلسات وتوقف مزود الهوية وخطة الانتقال والأخطاء الشائعة، وثلاث صور جديدة.
نشرة عرب رووت | ArabRoot

معرفة تستحق مكاناً في بريدك.

مقالات مختارة وأدوات مفيدة وأفكار لمشروعك القادم، في رسالة واحدة كل أسبوع.

يمكنك إلغاء الاشتراك متى شئت. الخصوصية

تم استلام طلبك. افتح بريدك واضغط رابط التأكيد لإتمام الاشتراك.