كيفية دمج تطبيقك كإطار iframe في B2CORE

تعرّف على كيفية دمج تطبيق ويب تابع لجهة خارجية في B2CORE كإطار iframe، بما في ذلك إعداد الخادم، ومزامنة النسق واللغة، والمصادقة المستندة إلى JWT عبر واجهة postMessage API

يدعم B2CORE تضمين تطبيقات الويب التابعة لجهات خارجية مباشرةً في واجهة المستخدم الخاصة بالعميل عبر إطار iframe. عند إعداد عنصر قائمة مخصص بسلوك Iframe، يقوم B2CORE بتحميل تطبيقك داخل الواجهة، مما يوفر تجربة سلسة للعملاء دون مغادرة المنصة.

يغطي هذا الدليل جانبين: إعداد عنصر القائمة المخصص في Back Office الخاص بـ B2CORE، وتجهيز تطبيقك للعمل بشكل صحيح داخل إطار iframe الخاص بـ B2CORE.

المتطلبات الأساسية

قبل المتابعة، تأكد مما يلي:

الخطوة 1. إعداد الخادم للسماح بالتضمين في إطار iframe

بشكل افتراضي، تمنع معظم خوادم الويب وأطر العمل تضمين الصفحات في إطارات iframe على نطاقات أخرى. للسماح لـ B2CORE بتحميل تطبيقك، يجب إعداد رؤوس استجابة HTTP المناسبة على خادمك.

تحتاج إلى تعيين رأس واحد أو كليهما من الرؤوس التالية:

Content-Security-Policy

يتحكم رأس Content-Security-Policy باستخدام التوجيه frame-ancestors في المصادر المسموح لها بتضمين صفحتك. عيّن هذا الرأس ليشمل مصدر مثيل B2CORE الخاص بك:

Content-Security-Policy: frame-ancestors 'self' https://portal.example.com

استبدل https://portal.example.com بالمصدر الفعلي لواجهة مستخدم B2CORE التي يستخدمها عملاؤك. يمكنك تحديد مصادر متعددة مفصولة بمسافات إذا كان تطبيقك يحتاج إلى التضمين عبر عدة مثيلات من B2CORE.

لمزيد من المعلومات، راجع وثائق Content-Security-Policy على MDN.

X-Frame-Options

رأس X-Frame-Options هو آلية أقدم تحقق نتيجة مشابهة. إذا كنت تستخدمه، فعيّنه على ALLOW-FROM مع مصدر B2CORE الخاص بك:

X-Frame-Options: ALLOW-FROM https://portal.example.com

لا تدعم جميع المتصفحات توجيه X-Frame-Options: ALLOW-FROM. يُوصى باستخدام رأس Content-Security-Policy مع التوجيه frame-ancestors كآلية أساسية، وإضافة X-Frame-Options فقط كخيار احتياطي للعملاء الأقدم.

لمزيد من المعلومات، راجع وثائق X-Frame-Options على MDN.

الخطوة 2. إضافة عنصر قائمة مخصص في Back Office الخاص بـ B2CORE

لجعل تطبيقك متاحًا للعملاء، أضف عنصر قائمة مخصصًا بسلوك iframe:

انتقل إلى Promotion > Menu.

انقر على أيقونة العين في صف General لعرض شجرة القائمة.

انقر على +Create في الزاوية العلوية اليمنى من الصفحة.

املأ الحقول المطلوبة:

  • في حقل Name، أدخل اسمًا فريدًا لعنصر القائمة.
  • في حقل Caption، أدخل التسمية التي سيراها العملاء في القائمة.
  • في حقل External URL، حدد عنوان URL لتطبيقك.
  • في حقل Icon، حدد عنوان URL لأيقونة SVG (16x16 px، أحادية اللون، بخلفية شفافة).
  • في القائمة المنسدلة Custom Behavior، حدد Iframe.

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

  • لتقييد الظهور على مستويات تحقق محددة، حدد المستويات المناسبة في القائمة المنسدلة Verification Level Allowance.
  • لتقييد الظهور على أنواع عملاء محددة، حدد الأنواع المقابلة في القائمة المنسدلة Client Type Allowance.

فعّل مربع الاختيار Visible لإظهار العنصر في القائمة.

انقر على Save لإضافة عنصر القائمة المخصص.

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

يتوفر خياران آخران للسلوك لعناصر القائمة المخصصة: Same tab (يفتح عنوان URL في علامة تبويب المتصفح الحالية) وNew tab (يفتح عنوان URL في علامة تبويب متصفح جديدة). خيار iframe هو الخيار الوحيد الذي يضمّن تطبيقك داخل واجهة B2CORE.

الخطوة 3 (اختياري). تنفيذ بروتوكول اتصال postMessage

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

مرجع الرسائل

الرسائل من تطبيقك إلى B2CORE

نوع الرسالةالوصفالحمولة
embed-iframe-readyيشير إلى أن إطار iframe تم تحميله وجاهز لتلقي الرسائل.{ type: "embed-iframe-ready" }
embed-request-jwt-tokenيطلب رمز مصادقة JWT من B2CORE.{ type: "embed-request-jwt-token" }

الرسائل من B2CORE إلى تطبيقك

نوع الرسالةالوصفالحمولة
embed-theme-changeتُرسل كلما تغير نسق واجهة مستخدم B2CORE (ومرة فورًا بعد embed-iframe-ready).{ type: "embed-theme-change", theme: "dark-theme" | "light-theme" }
embed-language-changeتُرسل كلما تغيرت لغة واجهة مستخدم B2CORE (ومرة فورًا بعد embed-iframe-ready).{ type: "embed-language-change", lang: "<language-code>" }
embed-jwt-tokenاستجابة ناجحة لطلب رمز مميز.{ type: "embed-jwt-token", token: "<jwt-string>", expiresAt: "<ISO-8601>" }
embed-jwt-token-errorاستجابة خطأ عند فشل إنشاء الرمز المميز.{ type: "embed-jwt-token-error", error: "<error-message>" }
embed-logoutتُرسل عندما يسجل مستخدم B2CORE الخروج. يصبح أي رمز مميز صدر سابقًا لتطبيقك غير صالح.{ type: "embed-logout" }

يحتوي الحقل lang على رمز لغة ISO 639-1 بأحرف صغيرة (على سبيل المثال، en أو de أو ar) يطابق اللغة المحددة حاليًا في واجهة مستخدم B2CORE.

يرتبط رمز JWT المميز الصادر عبر embed-jwt-token بمستخدم B2CORE الذي كان مسجل الدخول عند إصدار الرمز. عندما يسجل ذلك المستخدم الخروج، يرسل B2CORE الرسالة embed-logout ويجب عدم استخدام الرمز المميز بعد ذلك. تخلص من أي رمز مميز مخزن مؤقتًا، وأوقف عمليات التحديث المجدولة، وامسح الحالة الخاصة بالمستخدم عند تلقي هذه الرسالة. إذا سجل مستخدم مختلف الدخول بعد ذلك، فاطلب رمزًا مميزًا جديدًا باستخدام embed-request-jwt-token — سيتم إصدار رمز مميز جديد للمستخدم الجديد.

تدفق الاتصال

يتبع تسلسل الرسائل بين تطبيقك وB2CORE هذا النمط:

sequenceDiagram
    participant App as Your App (iframe)
    participant B2CORE as B2CORE (host)

    App->>B2CORE: embed-iframe-ready
    B2CORE-->>App: embed-theme-change (initial theme)
    B2CORE-->>App: embed-language-change (initial language)
    App->>B2CORE: embed-request-jwt-token
    alt success
        B2CORE-->>App: embed-jwt-token
    else failure
        B2CORE-->>App: embed-jwt-token-error
    end
    Note over App,B2CORE: Token nears expiry...
    App->>B2CORE: embed-request-jwt-token
    B2CORE-->>App: embed-jwt-token
    Note over App,B2CORE: User toggles theme...
    B2CORE-->>App: embed-theme-change
    Note over App,B2CORE: User changes language...
    B2CORE-->>App: embed-language-change
    Note over App,B2CORE: User logs out...
    B2CORE-->>App: embed-logout

الإشارة إلى الجاهزية. عند انتهاء تحميل صفحتك، أرسل رسالة embed-iframe-ready إلى B2CORE. يخبر هذا المضيف بأن تطبيقك جاهز لتلقي البيانات.

تلقي النسق الحالي. يستجيب B2CORE برسالة embed-theme-change التي تحتوي على النسق الحالي (dark-theme أو light-theme). طبّق النسق على واجهة المستخدم الخاصة بك. ستتلقى هذه الرسالة أيضًا كلما بدّل المستخدم النسق.

تلقي اللغة الحالية. يستجيب B2CORE أيضًا برسالة embed-language-change التي تحتوي على رمز اللغة المحدد حاليًا في واجهة مستخدم B2CORE (على سبيل المثال، en أو ar). طبّق اللغة المحلية المقابلة على واجهة المستخدم الخاصة بك. ستتلقى هذه الرسالة مجددًا كلما غيّر المستخدم اللغة.

طلب رمز مصادقة مميز. عندما تحتاج إلى تحديد المستخدم الحالي، أرسل embed-request-jwt-token. يستجيب B2CORE إما برسالة embed-jwt-token (تحتوي على JWT ووقت انتهاء صلاحيته) أو برسالة embed-jwt-token-error إذا فشل إنشاء الرمز المميز.

تحديث الرمز المميز قبل انتهاء الصلاحية. يحتوي JWT على وقت انتهاء صلاحية محدد في الحقل expiresAt (بتنسيق ISO 8601). اطلب رمزًا مميزًا جديدًا قبل انتهاء صلاحية الرمز الحالي للحفاظ على وصول دون انقطاع.

معالجة تسجيل الخروج. عندما يسجل مستخدم B2CORE الخروج، يرسل B2CORE الرسالة embed-logout. عند تلقيها، تخلص من الرمز المميز المخزن مؤقتًا، وألغِ أي تحديث مجدول، وامسح الحالة الخاصة بالمستخدم حتى لا تتسرب أي بيانات إلى المستخدم التالي. إذا سجل مستخدم آخر الدخول بعد ذلك، فاطلب رمزًا مميزًا جديدًا باستخدام embed-request-jwt-token.

مثال على التعليمات البرمجية

مقتطف JavaScript كامل يمكنك تضمينه في تطبيقك:

(function () {
  const B2CORE_ORIGIN = '*'; // Replace with your B2CORE instance origin for production

  let currentToken = null;
  let tokenRefreshTimer = null;

  // --- Send a message to B2CORE ---
  function sendToHost(message) {
    window.parent.postMessage(message, B2CORE_ORIGIN);
  }

  // --- Handle incoming messages from B2CORE ---
  function handleMessage(event) {
    const data = event.data;
    if (!data || !data.type) return;

    switch (data.type) {
      case 'embed-theme-change':
        applyTheme(data.theme);
        break;

      case 'embed-language-change':
        applyLanguage(data.lang);
        break;

      case 'embed-jwt-token':
        handleToken(data.token, data.expiresAt);
        break;

      case 'embed-jwt-token-error':
        console.error('Token error from B2Core:', data.error);
        break;

      case 'embed-logout':
        handleLogout();
        break;
    }
  }

  // --- Apply theme to your UI ---
  function applyTheme(theme) {
    document.documentElement.setAttribute('data-theme', theme);
  }

  // --- Apply language to your UI ---
  function applyLanguage(lang) {
    document.documentElement.setAttribute('lang', lang);
  }

  // --- Handle received JWT token ---
  function handleToken(token, expiresAt) {
    currentToken = token;

    // Schedule a refresh 2 minutes before expiry
    if (tokenRefreshTimer) {
      clearTimeout(tokenRefreshTimer);
    }

    const refreshIn = new Date(expiresAt).getTime() - Date.now() - 2 * 60 * 1000;

    if (refreshIn > 0) {
      tokenRefreshTimer = setTimeout(requestToken, refreshIn);
    } else {
      requestToken();
    }
  }

  // --- Request a JWT token from B2CORE ---
  function requestToken() {
    sendToHost({ type: 'embed-request-jwt-token' });
  }

  // --- Handle B2CORE user logout ---
  function handleLogout() {
    // The token is bound to the user who just logged out — stop using it.
    currentToken = null;

    if (tokenRefreshTimer) {
      clearTimeout(tokenRefreshTimer);
      tokenRefreshTimer = null;
    }

    // Clear any user-specific state in your app here.
  }

  // --- Initialize ---
  window.addEventListener('message', handleMessage);
  sendToHost({ type: 'embed-iframe-ready' });
  requestToken();
})();

استبدل قيمة B2CORE_ORIGIN بالمصدر الفعلي لمثيل B2CORE الخاص بك (على سبيل المثال، 'https://portal.example.com') في بيئة الإنتاج. لا يُقبل استخدام '*' إلا أثناء التطوير، لأنه يسمح لأي مصدر بالاتصال بتطبيقك.

تعريفات أنواع TypeScript

إذا كان تطبيقك مبنيًا باستخدام TypeScript، فيمكنك استخدام تعريفات الأنواع التالية:

type EmbedTheme = 'dark-theme' | 'light-theme';

// Messages: Your App -> B2CORE
interface EmbedIframeReadyMessage {
  readonly type: 'embed-iframe-ready';
}

interface EmbedRequestJwtTokenMessage {
  readonly type: 'embed-request-jwt-token';
}

type EmbedOutboundMessage = EmbedIframeReadyMessage | EmbedRequestJwtTokenMessage;

// Messages: B2CORE -> Your App
interface EmbedThemeChangeMessage {
  readonly type: 'embed-theme-change';
  readonly theme: EmbedTheme;
}

interface EmbedLanguageChangeMessage {
  readonly type: 'embed-language-change';
  readonly lang: string; // ISO 639-1 code, e.g. "en", "de", "ar"
}

interface EmbedJwtTokenMessage {
  readonly type: 'embed-jwt-token';
  readonly token: string;
  readonly expiresAt: string; // ISO 8601
}

interface EmbedJwtTokenErrorMessage {
  readonly type: 'embed-jwt-token-error';
  readonly error: string;
}

interface EmbedLogoutMessage {
  readonly type: 'embed-logout';
}

type EmbedInboundMessage =
  | EmbedThemeChangeMessage
  | EmbedLanguageChangeMessage
  | EmbedJwtTokenMessage
  | EmbedJwtTokenErrorMessage
  | EmbedLogoutMessage;

الخطوة 4 (اختياري). التحقق من رمز JWT المميز

يمكن التحقق من رمز JWT المميز الصادر عن B2CORE باستخدام نقطة نهاية JSON Web Key Set (JWKS) التي توفرها واجهة B2CORE API (الواجهة الخلفية للوحة الإدارة). يكون هذا عادةً نطاق API/admin، وليس نطاق واجهة المستخدم الموجهة للعملاء:

https://api.<your-domain>/.well-known/jwks.json

استخدم نقطة النهاية هذه لاسترداد المفاتيح العامة اللازمة للتحقق من توقيع الرمز المميز. تدعم معظم مكتبات JWT التحقق المستند إلى JWKS مباشرةً.

للفحص اليدوي أثناء التطوير، يمكنك فك ترميز رموز JWT المميزة والتحقق منها باستخدام أداة فك ترميز JWT.

آخر تحديث في

في هذه الصفحة