Comment intégrer votre application en tant qu’iframe dans B2CORE

Découvrez comment intégrer une application web tierce dans B2CORE en tant qu’iframe, y compris la configuration du serveur, la synchronisation du thème et de la langue, ainsi que l’authentification basée sur JWT via l’API postMessage

B2CORE prend en charge l’intégration d’applications web tierces directement dans l’interface client via une iframe. Lorsqu’un élément de menu personnalisé est configuré avec le comportement Iframe, B2CORE charge votre application dans l’interface, offrant une expérience fluide aux clients sans quitter la plateforme.

Ce guide couvre deux aspects : la configuration de l’élément de menu personnalisé dans le Back Office B2CORE et la préparation de votre application afin qu’elle fonctionne correctement dans l’iframe B2CORE.

Prérequis

Avant de poursuivre, assurez-vous que les conditions suivantes sont remplies :

Étape 1. Configurez votre serveur pour autoriser l’intégration dans une iframe

Par défaut, la plupart des serveurs web et des frameworks empêchent l’intégration de pages dans des iframes sur d’autres domaines. Pour permettre à B2CORE de charger votre application, vous devez configurer les en-têtes de réponse HTTP appropriés sur votre serveur.

Vous devez définir un ou les deux en-têtes suivants :

Content-Security-Policy

L’en-tête Content-Security-Policy avec la directive frame-ancestors contrôle les origines autorisées à intégrer votre page. Définissez cet en-tête pour inclure l’origine de votre instance B2CORE :

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

Remplacez https://portal.example.com par l’origine réelle de l’interface B2CORE utilisée par vos clients. Vous pouvez spécifier plusieurs origines séparées par des espaces si votre application doit être intégrée dans plusieurs instances B2CORE.

Pour plus d’informations, consultez la documentation Content-Security-Policy sur MDN.

X-Frame-Options

L’en-tête X-Frame-Options est un mécanisme plus ancien qui permet d’obtenir un résultat similaire. Si vous l’utilisez, définissez-le sur ALLOW-FROM avec votre origine B2CORE :

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

La directive X-Frame-Options: ALLOW-FROM n’est pas prise en charge par tous les navigateurs. Il est recommandé d’utiliser l’en-tête Content-Security-Policy avec la directive frame-ancestors comme mécanisme principal et d’inclure X-Frame-Options uniquement comme solution de secours pour les clients plus anciens.

Pour plus d’informations, consultez la documentation X-Frame-Options sur MDN.

Étape 2. Ajoutez un élément de menu personnalisé dans le Back Office B2CORE

Pour rendre votre application accessible aux clients, ajoutez un élément de menu personnalisé avec le comportement iframe :

Accédez à Promotion > Menu.

Cliquez sur l’icône œil dans la ligne General pour afficher l’arborescence du menu.

Cliquez sur +Create dans le coin supérieur droit de la page.

Renseignez les champs obligatoires :

  • Dans le champ Name, saisissez un nom unique pour l’élément de menu.
  • Dans le champ Caption, saisissez le libellé que les clients verront dans le menu.
  • Dans le champ External URL, indiquez l’URL de votre application.
  • Dans le champ Icon, indiquez l’URL d’une icône SVG (16x16 px, monochrome, arrière-plan transparent).
  • Dans la liste déroulante Custom Behavior, sélectionnez Iframe.

Configurez des restrictions facultatives si nécessaire :

  • Pour limiter la visibilité à des niveaux de vérification spécifiques, sélectionnez les niveaux appropriés dans la liste déroulante Verification Level Allowance.
  • Pour limiter la visibilité à des types de clients spécifiques, sélectionnez les types correspondants dans la liste déroulante Client Type Allowance.

Activez la case à cocher Visible pour afficher l’élément dans le menu.

Cliquez sur Save pour ajouter l’élément de menu personnalisé.

Lorsque les clients cliquent sur cet élément de menu, votre application se charge dans une iframe au sein de l’interface B2CORE.

Deux autres options de comportement sont disponibles pour les éléments de menu personnalisés : Same tab (ouvre l’URL dans l’onglet actuel du navigateur) et New tab (ouvre l’URL dans un nouvel onglet du navigateur). L’option iframe est la seule qui intègre votre application dans l’interface B2CORE.

Étape 3 (facultative). Implémentez le protocole de communication postMessage

Si votre application doit identifier l’utilisateur B2CORE authentifié, correspondre au thème de l’interface B2CORE ou suivre la langue sélectionnée par l’utilisateur, vous pouvez implémenter le protocole de communication postMessage décrit ci-dessous. Cette étape est facultative : si votre application ne nécessite pas d’authentification utilisateur, de synchronisation du thème ou de synchronisation de la langue, vous pouvez l’ignorer.

Référence des messages

Messages envoyés par votre application à B2CORE

Type de messageDescriptionCharge utile
embed-iframe-readyIndique que l’iframe est chargée et prête à recevoir des messages.{ type: "embed-iframe-ready" }
embed-request-jwt-tokenDemande un jeton d’authentification JWT à B2CORE.{ type: "embed-request-jwt-token" }

Messages envoyés par B2CORE à votre application

Type de messageDescriptionCharge utile
embed-theme-changeEnvoyé chaque fois que le thème de l’interface B2CORE change (et une fois immédiatement après embed-iframe-ready).{ type: "embed-theme-change", theme: "dark-theme" | "light-theme" }
embed-language-changeEnvoyé chaque fois que la langue de l’interface B2CORE change (et une fois immédiatement après embed-iframe-ready).{ type: "embed-language-change", lang: "<language-code>" }
embed-jwt-tokenRéponse réussie à une demande de jeton.{ type: "embed-jwt-token", token: "<jwt-string>", expiresAt: "<ISO-8601>" }
embed-jwt-token-errorRéponse d’erreur lorsque la génération du jeton échoue.{ type: "embed-jwt-token-error", error: "<error-message>" }
embed-logoutEnvoyé lorsque l’utilisateur B2CORE se déconnecte. Tout jeton précédemment émis à votre application n’est alors plus valide.{ type: "embed-logout" }

Le champ lang contient un code de langue ISO 639-1 en minuscules (par exemple, en, de, ar) correspondant à la langue actuellement sélectionnée dans l’interface B2CORE.

Un jeton JWT émis via embed-jwt-token est lié à l’utilisateur B2CORE qui était connecté au moment de son émission. Lorsque cet utilisateur se déconnecte, B2CORE envoie embed-logout et le jeton ne doit plus être utilisé. Supprimez tout jeton mis en cache, arrêtez les actualisations planifiées et effacez l’état spécifique à l’utilisateur à la réception de ce message. Si un autre utilisateur se connecte ensuite, demandez un nouveau jeton avec embed-request-jwt-token — un nouveau jeton est émis pour le nouvel utilisateur.

Flux de communication

La séquence des messages entre votre application et B2CORE suit ce modèle :

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

Signalez que vous êtes prêt. Lorsque votre page finit de se charger, envoyez le message embed-iframe-ready à B2CORE. Cela indique à l’hôte que votre application est prête à recevoir des données.

Recevez le thème actuel. B2CORE répond avec embed-theme-change, qui contient le thème actuel (dark-theme ou light-theme). Appliquez le thème à votre interface. Vous recevrez également ce message chaque fois que l’utilisateur change de thème.

Recevez la langue actuelle. B2CORE répond également avec embed-language-change, qui contient le code de langue actuellement sélectionné dans l’interface B2CORE (par exemple, en ou ar). Appliquez les paramètres régionaux correspondants à votre interface. Vous recevrez à nouveau ce message chaque fois que l’utilisateur change de langue.

Demandez un jeton d’authentification. Lorsque vous devez identifier l’utilisateur actuel, envoyez embed-request-jwt-token. B2CORE répond avec embed-jwt-token (contenant le JWT et son heure d’expiration) ou embed-jwt-token-error si la génération du jeton échoue.

Actualisez le jeton avant son expiration. Le JWT possède une heure d’expiration fournie dans le champ expiresAt (format ISO 8601). Demandez un nouveau jeton avant l’expiration du jeton actuel afin de maintenir un accès ininterrompu.

Gérez la déconnexion. Lorsque l’utilisateur B2CORE se déconnecte, B2CORE envoie embed-logout. À la réception de ce message, supprimez le jeton mis en cache, annulez toute actualisation planifiée et effacez l’état spécifique à l’utilisateur afin qu’aucune donnée ne soit divulguée à l’utilisateur suivant. Si un autre utilisateur se connecte ensuite, demandez un nouveau jeton avec embed-request-jwt-token.

Exemple de code

Un extrait JavaScript complet que vous pouvez inclure dans votre application :

(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();
})();

Remplacez la valeur B2CORE_ORIGIN par l’origine réelle de votre instance B2CORE (par exemple, 'https://portal.example.com') en production. L’utilisation de '*' est acceptable uniquement pendant le développement, car elle permet à toute origine de communiquer avec votre application.

Définitions de types TypeScript

Si votre application est construite avec TypeScript, vous pouvez utiliser les définitions de types suivantes :

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;

Étape 4 (facultative). Validez le jeton JWT

Le jeton JWT émis par B2CORE peut être validé par rapport au point de terminaison JSON Web Key Set (JWKS) exposé par l’API B2CORE (backend du panneau d’administration). Il s’agit généralement du domaine API/admin, et non du domaine de l’interface destinée aux clients :

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

Utilisez ce point de terminaison pour récupérer les clés publiques nécessaires à la vérification de la signature du jeton. La plupart des bibliothèques JWT prennent en charge la validation basée sur JWKS prête à l’emploi.

Pour une inspection manuelle pendant le développement, vous pouvez décoder et vérifier les jetons JWT à l’aide de l’outil de décodage JWT.

Dernière mise à jour le

Sur cette page