دمج مصادقة Entra ID في تطبيقات WinForms/WPF ── التشكيل العمليّ لـ MSAL.NET ووسيط WAM

· آخر تحديث: · · Windows, C#, .NET, WinForms, WPF, Entra ID, المصادقة, الأمان, الاستشارات التقنية

«نصنع شاشة تسجيل دخول لكلّ تطبيق أعمال داخليّ، وندير كلمات المرور في قاعدة بياناتنا الخاصّة. وفي كلّ مرّة يغادر فيها موظّف، نتعب من إيقاف حسابه في كلّ تطبيق على حدة» أو «لدينا Microsoft 365 مُفعَّل على مستوى الشركة كلّها، أفلا يمكن تسجيل الدخول مباشرةً بنفس ذلك الحساب؟». هذا موضوع يتزايد بثبات في السنوات الأخيرة ضمن استشارات تعديل تطبيقات سطح المكتب. وأحياناً يأتي على شكل طلب من قسم نظم المعلومات بـ«التوقّف عن إدارة كلمات المرور ذاتيّاً»، في سياق حوادث تسرّب كلمات المرور أو التوجّه نحو الثقة الصفريّة (Zero Trust).

بدايةً بالخلاصة: بالنسبة إلى المؤسّسات التي تستخدم Microsoft 365، فإنّ توجيه تسجيل الدخول في تطبيقات WinForms / WPF الداخليّة نحو Entra ID (المعروف سابقاً بـ Azure AD) استثمار سليم التوجّه. فلن يعود التطبيق يحتفظ بكلمات المرور مطلقاً، وتسري دفاعات جانب المستأجر ومراجعاته - كالمصادقة متعدّدة العوامل والوصول المشروط وسجلّات تسجيل الدخول - على التطبيقات الداخليّة مباشرةً. والتنفيذ أيضاً يقتصر على مكتبة MSAL.NET وبضع عشرات من أسطر الشيفرة.

غير أنّ هناك عدداً من المطبّات الخاصّة بتطبيقات سطح المكتب. فالبناء التقليديّ الذي «يستقبل اسم المستخدم وكلمة المرور عبر مربّعات نصّ ويتحقّق منهما خلف الكواليس» (ROPC) في طريقه رسميّاً إلى الإلغاء، ولا يجوز اعتماده في تطوير جديد. وما لم تُستَمرّ ذاكرة التخزين المؤقّت للرموز، تظهر شاشة تسجيل الدخول في كلّ مرّة يُشغَّل فيها التطبيق، كما أنّ استخدام الوسيط (broker/WAM) على Windows من عدمه يُحدِث فرقاً كبيراً في التجربة والأمان. يجمع هذا المقال، بالترتيب، تنظيماً موجزاً للمفاهيم، وتسجيل التطبيق، وتنفيذ MSAL.NET، وWAM، وذاكرة التخزين المؤقّت، وقرار التبنّي، ومطبّات التشغيل.

1. الخلاصة أوّلاً

  • عند التخلّي عن الإدارة الذاتيّة للمعرّفات وكلمات المرور والتوجّه نحو Entra ID، يصبح حفظ كلمات المرور، ومعالجة إعادة التعيين، وإيقاف حسابات المغادرين، ومراجعة سجلّات تسجيل الدخول، كلّها من مهام المستأجر بالكامل. وأكبر فائدة هي التقلّص الهائل في نطاق مسؤوليّة التطبيق.
  • تطبيق سطح المكتب عميل عامّ (public client). ولأنّ ملفّ exe يمكن تحليله لدى جهة التوزيع، فلا يمكنه (ولا يجوز له) أن يحمل سرّاً خاصّاً بالعميل (client secret). ويُشكَّل تسجيل التطبيق بدوره بوصفه عميلاً عامّاً.1
  • ROPC (Resource Owner Password Credentials)، الذي يحتفظ فيه التطبيق مباشرةً باسم المستخدم وكلمة المرور، مذكور رسميّاً على أنّه «أُلغِيَ (deprecated)»، وقد صدر دليل للانتقال منه. وهو لا يتوافق مع المصادقة متعدّدة العوامل والوصول المشروط، وهو في طريقه عمليّاً إلى التعطّل عن الاستخدام. اعتبر أنّ اعتماده في تطوير جديد ممنوع.23
  • التنفيذ يتمّ عبر MSAL.NET (‏Microsoft.Identity.Client)، ونمط الاستدعاء الأساسيّ الوحيد هو: استدعِ AcquireTokenSilent أوّلاً دائماً، وإن ظهر MsalUiRequiredException فاستدعِ AcquireTokenInteractive.4
  • على Windows، يُوصى بالمصادقة عبر وسيط WAM (‏Web Account Manager). وبسطر واحد من WithBroker، تحصل على تسجيل دخول موحّد مع الحساب المسجَّل دخوله بالفعل في Windows، ودعم للوصول المشروط وWindows Hello ومفاتيح FIDO، وربط رمز التحديث بالجهاز.5
  • إن نسيتَ جعل ذاكرة التخزين المؤقّت للرموز مستمرّة، ستظهر شاشة تسجيل الدخول في كلّ مرّة يُعاد فيها تشغيل التطبيق. أدرِج ذاكرة التخزين المؤقّت المشفَّرة من Microsoft.Identity.Client.Extensions.Msal منذ البداية.6
  • مصادقة Entra آليّة تفترض وجود شبكة. فهي لا تصلح للتطبيقات الميدانيّة التي يجب أن تعمل بلا اتّصال بالكامل، لذا ابدأ بتحديد إمكانيّة التبنّي من عدمها عبر جدول القرار في الفصل 8.

2. الصورة العامّة ── ماذا يعني التخلّي عن إدارة كلمات المرور الذاتيّة

2.1 ما مشكلة الإدارة الذاتيّة

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

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

عند تفويض المصادقة إلى Entra ID، تختفي هذه العناصر الأربعة من شيفرة التطبيق وتتوحّد في إدارة المستأجر. ومن يغادر العمل يكفي تعطيل حسابه في Entra ID ليصبح عاجزاً فوراً عن تسجيل الدخول في جميع التطبيقات، وتُحفَظ سجلّات تسجيل الدخول تلقائيّاً أيضاً. لا يكاد يوجد سبب يدعو مؤسّسة اعتمدت Microsoft 365 بالفعل إلى الاستمرار في مصادقة ذاتيّة الصنع. أمّا الآليّة المقابلة لتوجيه تسجيل الدخول إلى Windows نفسه نحو حساب Google في مؤسّسات Google Workspace، فقد تناولناها في «ما هو GCPW».

2.2 الحدّ الأدنى من المفاهيم ── العميل العامّ والرموز

نتجاوز الشرح الكتابيّ المدرسيّ لـ OAuth 2.0 / OpenID Connect، ونكتفي بسرد المفاهيم اللازمة فقط لتنفيذ تطبيق سطح المكتب.

المفهوم معناه في تطبيق سطح المكتب
العميل العامّ (public client) تطبيقات مثل ملفّات exe والتطبيقات المحمولة، لا تستطيع الاحتفاظ بسرٍّ (سرّ العميل) بأمان. تستطيع الحصول على الرموز نيابةً عن المستخدم فقط
العميل السرّيّ (confidential client) تطبيقات مثل خواديم الويب والعفاريت (daemons)، تستطيع الاحتفاظ بسرّ أو شهادة. تطبيق سطح المكتب ليس من هذا النوع
رمز الهوية (ID token) JWT يمثّل «من هذا الشخص». يكفي هذا وحده إن أردتَ وظيفة تسجيل الدخول فقط
رمز الوصول (access token) تصريح مرور لاستدعاء واجهة API معيّنة (كـ Microsoft Graph أو واجهة API خاصّة بالشركة). يحمل الوجهة (audience) والنطاق (scope) المخبوزَين فيه
رمز التحديث (refresh token) رمز لتحديث الرمزين أعلاه دون تفاعل. يُدار تلقائيّاً داخل ذاكرة التخزين المؤقّت الخاصّة بـ MSAL، ولا يظهر مباشرةً للتطبيق

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

2.3 ROPC طريقة انتهى عصرها ── نتيجة التحقّق من المصادر الرسميّة

الفكرة التقليديّة تميل إلى القول: «يكفي أن نستقبل اسم المستخدم وكلمة المرور عبر شاشة تسجيل دخول خاصّة بنا، ثمّ نطلب من Entra ID التحقّق منهما خلف الكواليس». هذا هو ROPC (تمرير اسم المستخدم وكلمة المرور مباشرةً)، وهو لا يزال موجوداً في MSAL.NET باسم AcquireTokenByUsernamePassword، لكنّ الوصف الحاليّ في الوثائق الرسميّة واضح.

  • مذكور صراحةً أنّ ROPC الموجَّه للعملاء العامّين «أُلغِيَ (deprecated) بسبب المخاطر الأمنيّة»، وقد نُشر دليل للانتقال إلى تدفّقات أكثر أماناً.3
  • ROPC غير متوافق مع المصادقة متعدّدة العوامل والوصول المشروط. فالمستخدمون الذين تُلزمهم سياسة المستأجر بالمصادقة متعدّدة العوامل يُحظَرون ولا يستطيعون تسجيل الدخول عبر هذا التدفّق.2
  • لا يعمل تسجيل الدخول الموحّد (SSO)، ولا يمكن استخدام حسابات Microsoft الشخصيّة، ولا يمكن للحسابات الخالية من كلمة المرور (FIDO أو Authenticator) تسجيل الدخول أيضاً.2
  • كما يتّجه جانب واجهات API الخاصّة بـ Microsoft للويب نحو قبول الرموز التي خضعت للمصادقة متعدّدة العوامل فقط، وتكتب الوثائق الرسميّة نفسها: «التطبيقات المعتمِدة على ROPC ستُستَبعَد (locked out). على تطبيقات سطح المكتب الانتقال إلى مصادقة قائمة على الوسيط (broker)».2

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

التدفّق مكان الاستخدام
التفاعليّ (وسيط / متصفّح) تطبيق GUI عاديّ. الخيار الأساسيّ
تدفّق رمز الجهاز (device code flow) بيئات لا يمكن فيها عرض متصفّح (كطرفيّة SSH البعيدة مثلاً). يعرض عنوان URL ورمزاً، ويُطلَب من المستخدم تسجيل الدخول عبر متصفّح على جهاز آخر

3. تسجيل التطبيق ── الإعداد في مركز إدارة Entra

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

3.1 التسجيل نفسه

أنشئ التسجيل من [App registrations] ← [New registration] في مركز إدارة Microsoft Entra (entra.microsoft.com).7

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

3.2 عنوان URI لإعادة التوجيه ── المنصّة هي “تطبيقات الهاتف المحمول وسطح المكتب”

هذا إعلان عن المكان الذي يُستقبَل فيه الرمز بعد المصادقة. اختر [Authentication] ← [Add a platform] ← [Mobile and desktop applications]، وسجِّل عنوان URI المناسب لطريقة المصادقة.1

طريقة المصادقة عنوان URI لإعادة التوجيه الذي يُسجَّل
وسيط WAM (الخيار الأساسيّ، الفصل 5) ms-appx-web://microsoft.aad.brokerplugin/{معرّف العميل}
متصفّح النظام http://localhost
متصفّح مضمَّن https://login.microsoftonline.com/common/oauth2/nativeclient

لا يُكتَب ms-appx-web://... الخاصّ بـ WAM في شيفرة MSAL، لكنّه إلزاميّ في جانب تسجيل التطبيق.8 وبالنظر إلى الرجوع الاحتياطيّ (fallback) إلى المتصفّح في البيئات التي لا يعمل فيها WAM (الفصل 5)، فمن العمليّ تسجيل العناصر الثلاثة في الجدول كلّها منذ البداية. ويجدر الانتباه بوجه خاصّ إلى سلوك WithDefaultRedirectUri()، إذ تعتمد الوجهة التي يُحلّ إليها على المنصّة: في .NET Framework تُحَلّ إلى https://login.microsoftonline.com/common/oauth2/nativeclient، وفي .NET (‏Core فما بعد) تُحَلّ إلى http://localhost.9 فإن كان تطبيق .NET Framework مسجَّلاً فيه ms-appx-web وhttp://localhost فقط، ورجع احتياطيّاً من WAM إلى المتصفّح، فسيحدث خطأ مصادقة بسبب عدم التطابق مع nativeclient. سجِّل العناصر الثلاثة كلّها، أو ثبِّتها صراحةً عبر WithRedirectUri(...). ومن المطبّات المعتادة أيضاً التسجيل عن طريق الخطأ في منصّة «Web»، ما يسبِّب خطأ مصادقة.

3.3 أذونات الوصول إلى API وموافقة المسؤول

من [API permissions]، أضِف إذن الوصول المفوَّض (delegated permission) لواجهة API التي يستدعيها التطبيق. وإن كان الهدف تسجيل الدخول وعرض الملفّ الشخصيّ فقط، يكفي User.Read من Microsoft Graph الممنوح افتراضيّاً.

بعد الإضافة، اطلب تنفيذ [Grant admin consent for (اسم المستأجر)].7 فبذلك تختفي نافذة موافقة كلّ مستخدم عند أوّل تسجيل دخول. وفي المستأجرين الذين عُطِّلت فيهم موافقة المستخدم نفسه، يتوقّف أوّل تسجيل دخول عند رسالة «يلزم موافقة المسؤول» دون موافقة المسؤول، لذا من المبدأ الأساسيّ في التطبيقات الموزَّعة داخليّاً إتمام موافقة المسؤول قبل التوزيع.

3.4 علامة “السماح بتدفّقات العميل العامّ”

علامة «السماح بتدفّقات العميل العامّ» (Allow public client flows) الموجودة ضمن الإعدادات التفصيليّة لـ [Authentication] تُضبَط على «نعم» عند استخدام تدفّقات لا تستعمل عنوان URI لإعادة التوجيه، كتدفّق رمز الجهاز أو مصادقة Windows المتكاملة.1 وهي ليست إلزاميّة إن اقتصر الأمر على التدفّق التفاعليّ (متصفّح / وسيط). ومن الجدير بالذكر أنّه لا يُنشَأ في هذا التسجيل لا سرّ العميل ولا شهادة. فبقاء حقل «Certificates & secrets» فارغاً هو الحالة الصحيحة للعميل العامّ (نظراً لكثرة الاستفسارات الناتجة عن الخلط بينهما، سنعود إلى هذا في الفصل 9).

4. التنفيذ عبر MSAL.NET ── الشكل الأساسيّ من Silent إلى Interactive

أضِف Microsoft.Identity.Client عبر NuGet. يكفي تذكّر نمط تنفيذ واحد فقط: استدعِ AcquireTokenSilent أوّلاً دائماً، وارجع احتياطيّاً إلى التفاعليّ فقط عند استقبال MsalUiRequiredException. وبما أنّ AcquireTokenInteractive مصمَّم بحيث لا ينظر إلى ذاكرة التخزين المؤقّت إطلاقاً، فإنّ استدعاءه مباشرةً يُظهر شاشة تسجيل الدخول في كلّ مرّة.4

using Microsoft.Identity.Client;

public sealed class AuthService
{
    private const string ClientId = "معرّف التطبيق (العميل)";
    private const string TenantId = "معرّف الدليل (المستأجر)";
    private static readonly string[] Scopes = { "User.Read" };

    private readonly IPublicClientApplication _app;

    public AuthService()
    {
        _app = PublicClientApplicationBuilder.Create(ClientId)
            .WithAuthority(AzureCloudInstance.AzurePublic, TenantId)
            .WithRedirectUri("http://localhost")  // لمتصفّح النظام
            .Build();
        // في الاستخدام الفعليّ، سجِّل هنا استمراريّة ذاكرة التخزين المؤقّت للرموز (الفصل 6)
    }

    public async Task<AuthenticationResult> SignInAsync(IntPtr ownerHwnd)
    {
        // 1. جرّب دائماً الحصول الصامت بالحساب المخزَّن في ذاكرة التخزين المؤقّت أوّلاً
        var accounts = await _app.GetAccountsAsync();
        var account = accounts.FirstOrDefault();
        try
        {
            return await _app.AcquireTokenSilent(Scopes, account)
                             .ExecuteAsync();
        }
        catch (MsalUiRequiredException)
        {
            // 2. أظهِر شاشة تسجيل الدخول فقط عند الحاجة إلى التفاعل.
            // نظراً لأنّ الوضع الافتراضيّ في .NET Framework هو WebView مضمَّن قديم الطراز،
            // حدِّد صراحةً إعادة التوجيه إلى http://localhost = متصفّح النظام
            // (‏.NET 6+ يستخدم أصلاً متصفّح النظام فقط)
            return await _app.AcquireTokenInteractive(Scopes)
                             .WithAccount(account)
                             .WithParentActivityOrWindow(ownerHwnd)
                             .WithUseEmbeddedWebView(false)
                             .ExecuteAsync();
        }
    }
}

يمرَّر مقبض النافذة المالكة (owner window handle) من جانب الاستدعاء. وذلك لمنع اختفاء نافذة المصادقة خلف التطبيق، وهو إلزاميّ في WAM.5 نقطة أخرى: لا تحذف WithUseEmbeddedWebView(false) في تطبيقات .NET Framework. فـ الوضع الافتراضيّ للمصادقة التفاعليّة في .NET Framework هو WebView مضمَّن، بينما إعادة التوجيه إلى http://localhost مخصّصة لمتصفّح النظام (فإن اختلّ التوافق بينهما، قد يقع الأمر في متصفّح مضمَّن قديم لا تعمل معه المصادقة المشروطة أو Windows Hello / FIDO، أو يحدث عدم تطابق في عنوان إعادة التوجيه).10 ابتداءً من .NET 6 لا يوجد WebView مضمَّن أصلاً، ويُستخدَم متصفّح النظام دائماً، لذا يصبح هذا التحديد زائداً لكن غير ضارّ.

// WinForms (داخل طريقة (method) لصفّ Form)
var result = await _authService.SignInAsync(this.Handle);

// WPF
var hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
var result = await _authService.SignInAsync(hwnd);

this.Text = $"تمّ تسجيل الدخول باسم: {result.Account.Username}";

نضيف بعض النقاط الجديرة بالانتباه.

  • استخدم نسخة (instance) واحدة من IPublicClientApplication في التطبيق كلّه وأعِد استخدامها. فبما أنّ لكلّ نسخة ذاكرة تخزين مؤقّتة خاصّة بها، فإنّ استدعاء Create في كلّ مرّة يُبطل عمل الحصول الصامت (silent).
  • MsalUiRequiredException ليس «حالة شاذّة»، بل تدفّق تحكّم اعتياديّ يعني «يلزم التفاعل». يحدث عند أوّل تشغيل، أو انتهاء صلاحيّة رمز التحديث، أو تغيّر متطلّبات الوصول المشروط، وما شابه.
  • الاستخدام الصحيح هو استدعاء AcquireTokenSilent في كلّ مرّة مباشرةً قبل استدعاء واجهة API. فإن وُجد رمز صالح في ذاكرة التخزين المؤقّت، يُعاد فوراً، وإن اقترب من الانتهاء يُجدَّد تلقائيّاً.4 لا يجوز الاحتفاظ برمز الوصول بنفسك وإدارة مدّة صلاحيّته.
  • الانتظار عبر .Result أو .Wait() في خيط الواجهة (UI thread) يسبِّب توقّفاً (deadlock) (راجع «async و UI thread في WPF/WinForms في صفحة واحدة»).

5. وسيط WAM ── التشكيل الموصى به على Windows

شيفرة الفصل 4 هي تشكيل يفتح متصفّحاً، لكن على Windows توجد طريقة أفضل بدرجة. WAM (‏Web Account Manager) وسيط مصادقة مدمَج في Windows 10 (الإصدار 1703 فما بعده) وWindows Server 2019 فما بعده، وتذكر الوثائق الرسميّة له الفوائد الأربع التالية.5

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

فإن كان جهاز الحاسوب الداخليّ منضمّاً إلى Entra (أو Hybrid Join)، تصبح التجربة: «تشغيل التطبيق ← اختيار حساب Windows ← اكتمال تسجيل الدخول فوراً»، دون إدخال كلمة مرور في أيّ مكان.

5.1 التنفيذ ── WithBroker والحزمة

لاستخدام WAM، يلزم MSAL.NET بإصدار 4.52.0 فما بعده، والحزمة الإضافيّة Microsoft.Identity.Client.Broker.5 أضِف WithBroker إلى المُنشئ (builder) الموجود في الفصل 4.

using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Broker;  // لـ WithBroker(BrokerOptions)

var brokerOptions = new BrokerOptions(BrokerOptions.OperatingSystems.Windows)
{
    Title = "نظام إدارة المخزون"  // العنوان المعروض في منتقي الحسابات
};

_app = PublicClientApplicationBuilder.Create(ClientId)
    .WithAuthority(AzureCloudInstance.AzurePublic, TenantId)
    .WithDefaultRedirectUri()
    .WithParentActivityOrWindow(() => _ownerHwnd)  // إلزاميّ في WAM
    .WithBroker(brokerOptions)
    .Build();

يمكن أيضاً تقوية جانب الحصول الصامت بسطر واحد. فعندما لا يوجد حساب في ذاكرة التخزين المؤقّت، يمكن تمرير PublicClientApplication.OperatingSystemAccount لتجربة تسجيل دخول صامت بـ«الحساب المسجَّل دخوله حاليّاً في Windows». وهذا نمط موصًى به رسميّاً يُنجز تسجيل الدخول دون أيّ نافذة منذ أوّل تشغيل.8

var accounts = await _app.GetAccountsAsync();
var account = accounts.FirstOrDefault()
              ?? PublicClientApplication.OperatingSystemAccount;
try
{
    return await _app.AcquireTokenSilent(Scopes, account).ExecuteAsync();
}
catch (MsalUiRequiredException)
{
    return await _app.AcquireTokenInteractive(Scopes).ExecuteAsync();
}

وكما ورد في القسم 3.2، سجِّل أيضاً ms-appx-web://microsoft.aad.brokerplugin/{معرّف العميل} في جانب تسجيل التطبيق ضمن منصّة «Mobile and desktop applications».5 فنسيان هذا يسبِّب فشل المصادقة التفاعليّة بخطأ في الوسيط. نقطة أخرى: WithDefaultRedirectUri() في المثال أعلاه تحدِّد عنوان URI لإعادة التوجيه عند الرجوع الاحتياطيّ إلى المتصفّح بسبب تعذّر استخدام WAM، وتعتمد الوجهة التي يُحلّ إليها على المنصّة (.NET Framework ← nativeclient، ‏.NET ← http://localhost).9 إن كانت العناصر الثلاثة في جدول القسم 3.2 مسجَّلة كلّها، يصلح أيّ منهما، لكن إن أردتَ تضييق التسجيل، حدِّده صراحةً عبر WithRedirectUri(...).

5.2 قيود WAM ── مطبّات إن لم تكن على علم بها

القيد المحتوى
نظام التشغيل Windows 10 (1703)+ / Windows Server 2019+. وفي ما قبل ذلك أو على Mac أو Linux، يرجع تلقائيّاً احتياطيّاً إلى المتصفّح5
موفِّر الهويّة مخصّص لـ Entra ID فقط. مرجعيّة (authority) Azure AD B2C وAD FS غير مدعومة (رجوع احتياطيّ إلى المتصفّح)5
سياق التنفيذ يفترض إمكانيّة إظهار واجهة مستخدم في جلسة مستخدم تفاعليّة. يُصدر خطأً بحسب التصميم في خدمات Windows، وجدولة المهام (خارج جلسة المستخدم)، والتنفيذ بمستخدم آخر عبر runas5

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

6. استمرار ذاكرة التخزين المؤقّت للرموز ── تجنّب ظهور شاشة تسجيل الدخول عند كلّ إعادة تشغيل

ذاكرة التخزين المؤقّت للرموز في MSAL.NET تبقى افتراضيّاً في الذاكرة فقط، وفي تطبيقات سطح المكتب يقع تنفيذ استمراريّتها على عاتق التطبيق نفسه. فما لم تُستمرَّ، يفشل AcquireTokenSilent في كلّ مرّة تُعاد فيها تشغيل العمليّة (process)، ويتحوّل الأمر إلى تسجيل دخول تفاعليّ.4 وسبب الاستفسارات من نوع «كان الأمر جيّداً في اختبار التبنّي، لكن وردت شكوى من الميدان بأنّ شاشة تسجيل الدخول تظهر كلّ صباح» يعود في الغالب إلى هذا بالذات.

الموصى به رسميّاً هو استخدام مكتبة ذاكرة التخزين المؤقّت متعدّدة المنصّات Microsoft.Identity.Client.Extensions.Msal (عبر NuGet).6

using Microsoft.Identity.Client.Extensions.Msal;

var storageProperties = new StorageCreationPropertiesBuilder(
        "msal_cache.dat",
        Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
            "KomuraSoft", "InventoryApp"))
    .Build();

var cacheHelper = await MsalCacheHelper.CreateAsync(storageProperties);
cacheHelper.RegisterCache(_app.UserTokenCache);  // يُسجَّل مرّة واحدة مباشرةً بعد Build()

تُحفَظ ذاكرة التخزين المؤقّت مشفَّرة على Windows. والمثال الوارد في الوثائق الرسميّة لتنفيذ ذاتيّ الصنع يشفِّر الرموز عبر ProtectedData (‏DPAPI، بنطاق DataProtectionScope.CurrentUser) ويحفظها في ملفّ، وتُعدّ Extensions.Msal مكتبة صقلت هذا الأسلوب إلى جودة إنتاجيّة.6 ومبدأ «حماية الأسرار الخاصّة بكلّ مستخدم عبر DPAPI بنطاق المستخدم» هو نفسه ما ورد بشأن ملفّات الإعدادات في «حفظ المعلومات السرّيّة في تطبيقات Windows - تجنّب الإعدادات النصّيّة الصريحة عبر DPAPI». تعامَل مع أيّ تنفيذ ذاتيّ يحفظ ذاكرة تخزين الرموز كنصّ JSON صريح بنفس درجة خطورة حفظ سلسلة الاتّصال (connection string) كنصّ صريح.

ثلاث ملاحظات على الجانب التشغيليّ.

  • حتّى عند استخدام WAM، تبقى استمراريّة ذاكرة التخزين المؤقّت لازمة. لأنّ MSAL يواصل حفظ رمز الهوية وبيانات وصف الحساب في ذاكرته المؤقّتة الخاصّة.8
  • المسار الأساسيّ للحفظ هو %LOCALAPPDATA%\اسم الشركة\اسم التطبيق. ولا يمكن فكّ التشفير على حاسوب آخر أو بمستخدم آخر بسبب ارتباط DPAPI بالمستخدم والجهاز، لكن لا ضرر فعليّاً سوى فشل الحصول الصامت والاضطرار إلى إعادة تسجيل الدخول.
  • يُنفَّذ «تسجيل الخروج» بحذف الحساب المسرود عبر GetAccountsAsync باستخدام RemoveAsync. ولا حاجة لحذف ملفّ ذاكرة التخزين المؤقّت. لكن ما يحذفه RemoveAsync هو ذاكرة MSAL المحليّة فقط، بينما تبقى جلسات WAM والمتصفّح وتسجيل الدخول إلى Windows كما هي. وبما أنّه يمكن إعادة تسجيل دخول نفس الحساب صامتاً في تسجيل الدخول التفاعليّ التالي، فإن أردتَ تحقيق تبديل الحسابات على حاسوب مشترك، صمِّم مع التمييز بين «حذف ذاكرة التخزين المؤقّت المحليّة» و«تسجيل الخروج الحقيقيّ» - كإضافة WithPrompt(Prompt.SelectAccount) إلى AcquireTokenInteractive لإظهار شاشة اختيار الحساب دائماً، أو استخدام نقطة نهاية تسجيل خروج المستأجر أيضاً بحسب المتطلّبات.

7. ماذا تفعل بالرمز الذي حصلت عليه ── ثلاثة تشكيلات

تنقسم طرق استخدام الرمز بعد نجاح المصادقة إلى ثلاثة أنماط. ويتغيّر الإعداد اللازم بحسب حجم ما تريد إنجازه.

التشكيل الرمز المُستخدَم ما يلزم إضافةً
(1) تسجيل الدخول فقط رمز الهوية (‏AuthenticationResult.Account / ClaimsPrincipal) لا شيء (فقط User.Read)
(2) استدعاء Microsoft Graph رمز وصول موجَّه لـ Graph إذن وصول Graph وموافقة بحسب واجهة API المراد استدعاؤها
(3) حماية واجهة API خاصّة بالشركة رمز وصول موجَّه لواجهة API الخاصّة تسجيل تطبيق ونشر نطاق (scope) على جانب API، والتحقّق من الرمز في جانب API

7.1 تشكيل تسجيل الدخول فقط ── البداية الأصغر

إن كان الهدف «مجرّد استبدال التحقّق الذاتيّ من كلمة المرور، دون استدعاء أيّ واجهة API سحابيّة»، يكفي مقارنة معلومات الحساب الناتجة عن تسجيل الدخول بجدول الصلاحيّات داخل التطبيق. استبدِل مفتاح جدول users بـمعرّف الكائن (object ID) في Entra (ثابت لا يتغيّر حتّى لو تغيّر UPN بتغيير اسم العائلة مثلاً)، واحذف عمود كلمة المرور. وبما أنّه يمكن استبدال المصادقة فقط دون تغيير تصميم قاعدة البيانات المحليّة، فهذا التشكيل هو الأسهل توصيةً كخطوة أولى.

7.2 استدعاء Microsoft Graph

إن أرسلتَ رمز وصول User.Read مباشرةً إلى Microsoft Graph، يمكنك الحصول على ملفّ المستخدم المسجَّل دخوله وصورته.

var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", result.AccessToken);
var me = await http.GetStringAsync("https://graph.microsoft.com/v1.0/me");

إن أردتَ التوسّع إلى التقويم، أو إرسال البريد الإلكترونيّ، أو إشعارات Teams، وما شابه، أضِف إذن الوصول المناظر (كـ Mail.Send) وأعِد أخذ موافقة المسؤول. وتصميم توجيه رسائل الإشعار من التطبيقات الداخليّة عبر Graph يتوافق مع ما تناولناه في «كيفيّة تصميم البريد الجماعيّ للشركات الصغيرة والمتوسّطة دون التقيّد بخدمة معيّنة».

7.3 حماية واجهة API خاصّة بالشركة ── حتّى التحقّق من audience والنطاق

إن كان التشكيل يقضي بأن يستدعي تطبيق سطح المكتب واجهة API خاصّة بالشركة، فأنشئ تسجيل تطبيق آخر لجانب API أيضاً، وانشر نطاقاً مثل api://{معرّف عميل API}/access_as_user، ويطلب جانب سطح المكتب الرمز بذلك النطاق. والمهمّ في جانب API هو أنّ إضافة [Authorize] وحدها غير كافية، وهذا مذكور صراحةً رسميّاً.11 وينبغي التحقّق من ثلاث مراحل.

  1. التوقيع والجهة المُصدِرة: هل هو JWT أصدرته Entra ID التابعة للمستأجر الصحيح (تتولّاه البرمجيّة الوسيطة (middleware) في حالة ASP.NET Core + Microsoft.Identity.Web)
  2. الوجهة (audience) - المطالبة aud: هل وجهة الرمز هي واجهة API هذه نفسها؟ لا تسمح بإعادة استخدام رمز موجَّه لـ Graph في واجهة API الخاصّة بالشركة
  3. النطاق - المطالبة scp: هل يحتوي على النطاق المتوقَّع؟ يمكن الإعلان عنه في Microsoft.Identity.Web عبر الصفة [RequiredScope("access_as_user")]11

إن أُغفِلت الخطوتان 2 و3، ينتج عنه «واجهة API يمرّ منها أيّ رمز يبدو صادراً عن Entra». اجعل هذا مع بند التحقّق من الاتّصال والمُدخَلات في «قائمة تحقّق للحدّ الأدنى من الأمان في تطوير تطبيقات Windows» موضوعاً لمراجعة التصميم معاً.

8. قرار التبنّي ── هل يجب إدخال مصادقة Entra في أداة داخليّة بحتة

لا يعني هذا أنّه ينبغي إدخالها في كلّ تطبيق داخليّ. نضع فيما يلي جدول قرار.

الحالة التوصية السبب
Microsoft 365 / Entra ID مُفعَّلان على مستوى الشركة كلّها + للتطبيق مفهوم تسجيل دخول أدخِلها يختفي عبء إدارة كلمات المرور الذاتيّة بالكامل. وتكلفة التنفيذ صغيرة
التطبيق يستدعي واجهة API خاصّة بالشركة أو موارد سحابيّة أدخِلها بنية المصادقة إلزاميّة لحماية واجهة API. وهي أضمن من اختراع رمز ذاتيّ الصنع
توجد متطلّبات مراجعة (تسجيل من استخدمها ومتى، إلزام المصادقة متعدّدة العوامل) أدخِلها تتوحّد سجلّات تسجيل الدخول والوصول المشروط في جانب المستأجر
أداة أحاديّة الوظيفة بلا مفهوم تسجيل دخول (أداة تحويل، عارض، إلخ) لا حاجة لا دافع لإضافة مصادقة. يكفي تسجيل الدخول إلى Windows
تعمل في بيئة معزولة تماماً عن الشبكة (خطّ إنتاج مغلق، حاسوب محمول للاستخدام الخارجيّ) غير ممكنة أو تحتاج تصميماً خاصّاً الشبكة إلزاميّة لأوّل تسجيل دخول وتجديد الرمز
Entra ID غير مُفعَّلة (AD محليّة فقط، أو Google Workspace فقط) ابحث عن حلّ بديل الأولى تناسبها مصادقة AD (مصادقة Windows المتكاملة)، والثانية تناسبها آليّة جانب Google

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

9. مطبّات التشغيل ── الاستفسارات التي تَرِد بعد التبنّي

الأمر لا ينتهي عند التبنّي، بل توجد استفسارات معتادة تَرِد في مرحلة التشغيل. نكتبها استباقيّاً فيما يلي.

  • «كان يعمل حتّى الأمس، فجأة لا يمكنني تسجيل الدخول»: المشتبه به الأوّل هو تغيّر سياسة الوصول المشروط. فإن فعَّل قسم نظم المعلومات مثلاً «حظر الأجهزة غير المسجَّلة»، يبدأ تسجيل الدخول بالفشل دون أن يتغيّر شيء في التطبيق. أسرع طريقة للتشخيص هي النظر في سبب الخطأ للمستخدم المعنيّ عبر سجلّ تسجيل الدخول في مركز إدارة Entra. وتشكيل WAM يرفع القدرة على التعامل مع متطلّبات السياسات، فيقلّل هذا النوع من الاحتكاك من الأساس.5
  • «وردني إشعار بانتهاء صلاحيّة السرّ، فهل هذا التطبيق بخير؟»: العميل العامّ لا يملك سرّاً ولا شهادة أصلاً، فلا وجود لانتهاء صلاحيّة. وإن وردك هذا الاستفسار، فإمّا أنّه خلط مع تسجيل تطبيق عميل سرّيّ، أو أنّ أحداً أنشأ سرّاً غير ضروريّ في تسجيل مخصّص لعميل عامّ (وفي الحالة الثانية يمكن حذفه دون مشكلة). عدم إمكانيّة حدوث توقّف بنيويّ بسبب انتهاء صلاحيّة سرّ ميزة خفيّة في هذا التشكيل.
  • «يظهر عند أوّل تشغيل رسالة “يلزم موافقة المسؤول”»: هذا نقص في موافقة المسؤول المذكورة في القسم 3.3. وحتّى عند إضافة إذن وصول لاحقاً، يبقى نفس العرض حتّى تُعاد الموافقة على الجزء المُضاف.
  • «لا يعمل عند دمجه في دفعة ليليّة»: كما ورد في القسم 5.2، يفترض WAM جلسة تفاعليّة. صمِّم المعالجة غير المأهولة تصميماً منفصلاً بأذونات التطبيق، لا بإعادة استخدام رمز مفوَّض من المستخدم.
  • التوزيع والتحديث: التصحيحات المتعلّقة بـ MSAL نشطة، ويلزم آليّة توصل تحديث المكتبة إلى جميع الأجهزة الطرفيّة. اجعل ذلك مقترناً بالتحقّق من مسار التحديث الذي كتبناه في «تصميم أمان التحديث التلقائيّ».

10. الخلاصة

يمكن تلخيص دعم مصادقة Entra ID في تطبيقات WinForms / WPF في النقاط الستّ التالية.

  • الهدف نفسه هو التخلّي عن الإدارة الذاتيّة لكلمات المرور. وتتوحّد الحفظ وإعادة التعيين ومعالجة المغادرين والمراجعة في جانب المستأجر
  • تطبيق سطح المكتب عميل عامّ. لا يستطيع حمل سرّ ولا يحتاج إليه
  • ROPC في طريقه إلى الإلغاء. لا تنشئ شاشة جديدة تحتفظ باسم المستخدم وكلمة المرور
  • التنفيذ يقتصر على نمط MSAL.NET: AcquireTokenSilentAcquireTokenInteractive
  • على Windows، دعم SSO والوصول المشروط وWindows Hello عبر وسيط WAM (‏WithBroker)
  • أدرِج استمراريّة ذاكرة التخزين المؤقّت للرموز (‏Extensions.Msal / حماية DPAPI) منذ البداية

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

مقالات ذات صلة

مجالات الاستشارة ذات الصلة

تتعامل شركة Komura Soft LLC مع دمج مصادقة Entra ID في تطبيقات WinForms / WPF القائمة (تصميم تسجيل التطبيق، وتنفيذ MSAL.NET، وخطّة الانتقال من المصادقة الذاتيّة)، ومراجعة تصميم التحقّق من الرموز لواجهات API الخاصّة بالشركة، وتشخيص أعطال تسجيل الدخول المرتبطة بالوصول المشروط.

المراجع

  1. Microsoft Learn، Desktop app that calls web APIs: Code configuration. حول عنوان URI لإعادة التوجيه لتطبيقات سطح المكتب (منصّة الهاتف المحمول وسطح المكتب، nativeclient / localhost)، ومعنى إعداد «السماح بتدفّقات العميل العامّ».  2 3

  2. Microsoft Learn، Microsoft identity platform and OAuth 2.0 Resource Owner Password Credentials. حول أنّه لا ينبغي استخدام ROPC، وعدم توافقه مع المصادقة متعدّدة العوامل وحظره، واتّجاه استبعاد التطبيقات المعتمِدة على ROPC، ووجوب انتقال تطبيقات سطح المكتب إلى مصادقة قائمة على الوسيط.  2 3 4

  3. Microsoft Learn، Desktop app that calls web APIs: Acquire a token using username and password. حول اعتبار تدفّق اسم المستخدم وكلمة المرور (ROPC) مُلغًى (deprecated) بسبب المخاطر الأمنيّة، والإرشاد إلى دليل الانتقال، وقيود عدم دعم المصادقة متعدّدة العوامل والوصول المشروط وSSO.  2

  4. Microsoft Learn، Get a token from the token cache using MSAL.NET. حول النمط الموصى به لاستدعاء AcquireTokenSilent أوّلاً والرجوع احتياطيّاً إلى التفاعليّ عند MsalUiRequiredException، والتحديث التلقائيّ عبر ذاكرة التخزين المؤقّت ورمز التحديث، ومسح ذاكرة التخزين المؤقّت بحذف الحساب.  2 3 4

  5. Microsoft Learn، Using MSAL.NET with Web Account Manager (WAM). حول فوائد الوسيط (تعزيز الأمان، ودعم Windows Hello والوصول المشروط وFIDO، ومنتقي الحسابات، وحماية الرموز)، وMSAL.NET 4.52.0+ وحزمة Microsoft.Identity.Client.Broker، وWithBroker وإلزاميّة مقبض النافذة الأبّ، وعنوان إعادة التوجيه ms-appx-web، وأنظمة التشغيل المدعومة والرجوع الاحتياطيّ، وقيود مثل إلزاميّة الجلسة التفاعليّة.  2 3 4 5 6 7 8 9

  6. Microsoft Learn، Token cache serialization. حول التوصية باستخدام ذاكرة التخزين المؤقّت متعدّدة المنصّات من Microsoft.Identity.Client.Extensions.Msal في تطبيقات سطح المكتب، وكيفيّة استخدام MsalCacheHelper، ومثال على التسلسل (serialization) الذاتيّ عبر ProtectedData (بنطاق DPAPI وCurrentUser).  2 3

  7. Microsoft Learn، Register an application with the Microsoft identity platform. حول خطوات تسجيل التطبيق في مركز إدارة Entra، واختيار أنواع الحسابات المدعومة، والحصول على معرّف العميل، وموافقة المسؤول.  2

  8. Microsoft Learn، Desktop app that calls web APIs: Acquire a token by using WAM. حول ضرورة استمراريّة ذاكرة التخزين المؤقّت للرموز حتّى عند استخدام WAM، والنمط الموصى به لتسجيل الدخول الصامت عبر OperatingSystemAccount، وإعداد عنوان إعادة التوجيه في جانب تسجيل التطبيق.  2 3

  9. Microsoft Learn، Default reply URI. حول اعتماد عنوان إعادة التوجيه الذي يضبطه WithDefaultRedirectUri على المنصّة (سطح مكتب .NET Framework: https://login.microsoftonline.com/common/oauth2/nativeclient، و.NET Core: http://localhost).  2

  10. Microsoft Learn، Using web browsers (MSAL.NET). حول جدول دعم المتصفّح بحسب الإطار (الوضع الافتراضيّ في .NET Framework 4.6.2+ هو المضمَّن، و.NET 6+ متصفّح النظام فقط)، وضرورة عنوان إعادة التوجيه http://localhost لمتصفّح النظام، والتبديل عبر WithUseEmbeddedWebView. 

  11. Microsoft Learn، Protected web API: Verify scopes and app roles. حول عدم كفاية الصفة [Authorize] وحدها، وضرورة التحقّق من المطالبة scp (النطاق)، والتحقّق التصريحيّ عبر الصفة RequiredScope في Microsoft.Identity.Web.  2

أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.

ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.

الأسئلة الشائعة

أسئلة شائعة حول موضوع هذه المقالة.

ما فائدة إدخال مصادقة Entra ID في تطبيقات WinForms/WPF؟
يصبح حفظ كلمات المرور، ومعالجة إعادة تعيينها، وإيقاف حسابات من يغادرون العمل، ومراجعة سجلّات تسجيل الدخول، كلّها من مهام المستأجر (tenant)، فيتقلّص نطاق مسؤوليّة التطبيق تقلّصاً كبيراً. فمن يغادر العمل يكفي تعطيل حسابه في Entra ID ليصبح عاجزاً فوراً عن تسجيل الدخول في جميع التطبيقات، كما تسري المصادقة متعدّدة العوامل والوصول المشروط مباشرةً على التطبيقات الداخليّة. والتنفيذ أيضاً يقتصر على مكتبة MSAL.NET وبضع عشرات من أسطر الشيفرة. لا يكاد يوجد سبب يدعو مؤسّسة اعتمدت Microsoft 365 بالفعل إلى الاستمرار في مصادقة ذاتيّة الصنع.
هل يمكن استخدام طريقة استقبال اسم المستخدم وكلمة المرور عبر شاشة خاصّة للمصادقة (ROPC)؟
اعتبر أنّ اعتماده في تطوير جديد ممنوع. فـ ROPC الموجَّه للعملاء العامّين مذكور رسميّاً على أنّه «أُلغِيَ (deprecated) بسبب المخاطر الأمنيّة»، وقد نُشر دليل للانتقال منه. ولأنّه غير متوافق مع المصادقة متعدّدة العوامل والوصول المشروط، فإنّ المستخدمين الذين تُلزمهم سياسة المستأجر بالمصادقة متعدّدة العوامل يُحظَرون ولا يستطيعون تسجيل الدخول. وبما أنّ إلزام المصادقة متعدّدة العوامل قد يحدث في أيّ وقت عبر إعداد جانب المستأجر، فحتّى لو كان يعمل الآن، فثمّة خطر أن يعجز جميع المستخدمين فجأة يوماً ما عن تسجيل الدخول.
هل من الأفضل استخدام وسيط WAM؟
على Windows، هو موصًى به. فبسطر واحد من WithBroker، تحصل على تسجيل دخول موحّد (SSO) مع الحساب المسجَّل دخوله بالفعل في Windows، ودعم للوصول المشروط وWindows Hello ومفاتيح FIDO، وربط رمز التحديث بالجهاز. فإن كان جهاز الحاسوب الداخليّ منضمّاً إلى Entra، تكتمل عمليّة تسجيل الدخول بمجرّد اختيار حساب Windows بعد تشغيل التطبيق، دون إدخال كلمة مرور. لكنّه مخصّص لـ Entra ID فقط، ولديه قيد يجعله يُصدر خطأً بحسب التصميم خارج جلسات المستخدم التفاعليّة، كخدمات Windows أو جدولة المهام.
لماذا تظهر شاشة تسجيل الدخول في كلّ مرّة يُعاد فيها تشغيل التطبيق؟
لأنّ ذاكرة التخزين المؤقّت للرموز غير مُستمرّة (persisted). فذاكرة تخزين الرموز في MSAL.NET تبقى افتراضيّاً في الذاكرة فقط، وفي تطبيقات سطح المكتب يقع تنفيذ الاستمراريّة على عاتق التطبيق نفسه. والموصى به رسميّاً هو حزمة Microsoft.Identity.Client.Extensions.Msal، حيث تُحفَظ ذاكرة التخزين المؤقّت مشفَّرة على Windows. وحتّى عند استخدام WAM، تبقى استمراريّة ذاكرة التخزين المؤقّت لازمة لحفظ رمز الهوية وبيانات وصف الحساب.

الملف الشخصي للمؤلف

صفحة الملف الشخصي لمؤلف المقالة.

غو كومورا

مؤسّس شركة كومورا سوفت ذ.م.م.

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

روابط عامة

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