CARL Source
Intégrer un site externe dans une iFrame
Personnalisation > Écran d'accueil > Intégrer un site externe dans une iFrame

CARL Source fournit une API permettant à un site externe, affiché via une iFrame, de communiquer avec CARL Source et avec la page qui embarque ce site externe.

Cette page décrit un mécanisme permettant à un site externe, affiché dans une iFrame de CARL Source, de dialoguer avec CARL Source via les APIs REST, sans qu'il soit nécessaire à l'utilisateur de se reconnecter.
Ce mécanisme utilise notamment une API ("/api/auth/v1/me"), et la gestion des entêtes HTTP CORS.

Autorisation CORS pour le site externe

Par défaut les navigateurs bloquent toutes les requêtes HTTP "cross domains", c'est-à-dire les requêtes issues de sites différents.
Pour autoriser cette communication, et autoriser le navigateur à propager l'identité de l'utilisateur jusqu'au site externe, il faut préciser ce domaine dans un paramètre système de CARL Source.
Dans le module "Système", se rendre dans la fonctionnalité "Configuration Système" et sur la partie "Authentification", renseigner pour le paramètre "crossOriginAllowedDomains" la liste des domaines autorisés à communiquer avec CARL Source.
Les domaines doivent être indiqués avec le protocole https (seul le protocole sécurisé permettant les échanges "cross domains") et si besoin le port utilisé. Les différents domaines déclarés doivent être séparés par des virgules.

Par exemple : https://externalSite1:8888,https://externalSite2

 

Création d'un widget sur l'écran d'accueil

Pour illustrer l'exemple, on ajoute un widget de type "Site externe" sur l'écran d'accueil.

Ce widget affichera notre site externe ("https://externalSite1:8888"), en lui indiquant également via un paramètre d'URL (par exemple ici "csUrl"), l'URL de base où est déployée l'instance de CARL Source.
Ceci est nécessaire si le site externe ne connait pas de façon statique l'adresse de l'instance de CARL Source, ou s'il peut fonctionner de façon multi-tenante pour plusieurs instances de CARL Source.
En effet il n'existe pas de façon fiable pour un site embarqué dans une iFame de récupérer l'adresse du site conteneur, quel que soit le navigateur.


Pour plus de détails sur ce type de widget, veuillez vous reporter à la partie Composant Site.

 

Exemples de pages dialoguant avec CARL Source

Ce chapitre décrit, à titre d'exemple, une page HTML et un code JavaScript qui récupèrent les informations sur l'utilisateur connecté dans CARL Source, et qui appellent les APIs REST de CARL Source de façon à obtenir des informations supplémentaires (par exemple : le site de l'utilisateur, son adresse mail, etc.).

La page HTML (représentant le site externe) affichée dans le widget :

Exemple page HTML
Copier le code
<!DOCTYPE html>
<html>
  <body>
    <script src="carlsource.js"></script>
 
    <h1>Landing page</h1>
    This is a landing page which can be embedded inside an iframe in CARL Source. This page can
    interract with CARL Source through its REST APIs with automatic transmission of connected user
    credentials. CORS requests <b>MUST</b> be enabled for this page domain through CARL Source
    system parameter : <b>"Authentication" > "crossOriginAllowedDomains"</b>
 
    <h2>Origin</h2>
    <ul>
      <li>Location: <tt id="locationTag">Waiting...</tt></li>
      <li>CARL Source location: <tt id="csUrlTag">Waiting...</tt></li>
    </ul>
 
    <h2>Currently connected user info</h2>
    <pre id="resultMe">Waiting...</pre>
 
    <h2>Actor info</h2>
    <pre id="resultActor">Waiting...</pre>
 
    <script>
      fetch_data();
    </script>
  </body>
</html>

 

Le code JavaScript qui récupère les informations et qui appelle les APIs REST de CARL Source :

carlsource.js
Copier le code
// Fetch CARL Source data and display them on page placeholders.
function fetch_data() {
  // Retrieve current page location URL.
  const currentPageLocationUrl = new URL(window.location.href);
  // Display it on page.
  document.getElementById("locationTag").innerText = currentPageLocationUrl.toString();
 
  // Extract CARL Source base URL from current page parameter.
  // There seams to be no reliable way to get caller's URL, so it's given by caller with parameter.
  if (currentPageLocationUrl.searchParams.has("csUrl")) {
    const csUrl = currentPageLocationUrl.searchParams.get("csUrl");
    // Normalizing URL by removing last "/" if any.
    const normalizedUrl = csUrl.endsWith("/") ? csUrl.substring(0, csUrl.length - 1) : csUrl;
    // Display given CARL Source base URL.
    document.getElementById("csUrlTag").innerText = normalizedUrl;
    // Then fetch CARL Source data through APIs.
    fetch_user_data(normalizedUrl);
  } else {
    // No CARL Source URL parameter, stop here.
    document.getElementById("csUrlTag").innerText = "Missing csUrl parameter !";
  }
}
 
function fetch_user_data(carlSourceLocation) {
  // Ensures the HTTP request is done with a CORS preflight request (mode: cors),
  // then the real request is done with browser sending the session cookie (credentials: include).
  const fetchOptions = { mode: "cors", credentials: "include" };
 
  // Get currently connected user data.
  fetch(carlSourceLocation + "/api/auth/v1/me", fetchOptions)
    .then((meResponse) => meResponse.json())
    .then((meJsonResponse) => {
      // The "/me" response provides ids for user, actor, and current session values. Display it.
      document.getElementById("resultMe").innerText = JSON.stringify(meJsonResponse, null, 2);
      // Query the "/actor" API to get data, useful for this page, which may be stored
      // in its xtraFields.
      const actorUrl = carlSourceLocation + "/api/entities/v1/actor/" + meJsonResponse.actorId
        + "?include=phones";
      return fetch(actorUrl, fetchOptions);
    })
    .then((actorResponse) => actorResponse.json())
    .then((actorJsonResponse) => {
      // Display "/actor" response.
      document.getElementById("resultActor").innerText = JSON.stringify(actorJsonResponse, null, 2);
    });
}

 

Résultat

La capture suivante montre le résultat, avec les informations obtenues par le site externe.