Aller au contenu de la page
Documentation
Documentation de Make Agent Fast

Sécurité et CSP

Protégez les agents intégrés grâce aux listes d'origines autorisées, aux politiques du navigateur et à une installation sans exposition d'identifiants.

En un coup d’œil

Protégez les agents intégrés grâce aux listes d'origines autorisées, aux politiques du navigateur et à une installation sans exposition d'identifiants.

Parcours d'installation de l'intégrationLe chargeur sur votre site communique avec l'agent hébergé
Votre site webHTML / appScript de chargementembed.jsInterface du widgetChat / voixAgent

Liste d'origines autorisées#

L'intégration est refusée par défaut, sauf si elle est activée et si l'origine parente exacte du navigateur est autorisée. Une origine se présente sous la forme scheme://hostname[:port] ; les chemins et les chaînes de requête n'en font pas partie.

Page hôteValeur de la liste d'autorisation
https://example.com/pricinghttps://example.com
https://www.example.com/helphttps://www.example.com
https://preview.example.com:8443/demohttps://preview.example.com:8443
http://localhost:3000http://localhost:3000

Ajoutez séparément les origines de production, de préproduction et locales. N'ajoutez pas de caractère générique pour résoudre une erreur d'installation : sinon, toute personne qui copie un slug public pourrait intégrer l'agent et consommer les crédits du site.

Content Security Policy#

Le loader a besoin de l'autorisation de script, le widget a besoin de l'autorisation de frame, et la requête d'apparence du loader peut nécessiter l'autorisation de connexion. Fusionnez ces sources dans les directives existantes de l'hôte ; ne remplacez pas une politique déjà éprouvée par cet exemple minimal.

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://makeagent.fast;
  frame-src https://makeagent.fast;
  connect-src 'self' https://makeagent.fast;

Si le site utilise script-src-elem, ajoutez-y également https://makeagent.fast. Le loader externe n'exige pas unsafe-inline, mais le framework de l'hôte peut avoir ses propres exigences en matière de nonce ou de hash. Une politique en mode « report-only » est utile pendant les tests :

Content-Security-Policy-Report-Only:
  script-src 'self' https://makeagent.fast;
  frame-src https://makeagent.fast;
  connect-src 'self' https://makeagent.fast;

Lorsque la console du navigateur signale une violation de CSP, modifiez la directive indiquée, et non default-src de façon générale, puis testez à nouveau la page publique.

Microphone et autorisations du navigateur#

Le loader crée l'iframe avec allow="microphone; autoplay; clipboard-write". Une Permissions Policy plus stricte au niveau de l'hôte peut toutefois annuler cette autorisation. Si la voix est activée, autorisez l'origine de la frame Make Agent Fast dans la réponse de l'hôte :

Permissions-Policy: microphone=(self "https://makeagent.fast")

Le visiteur doit également accorder l'accès au microphone dans le navigateur. Testez en HTTPS : les navigateurs restreignent normalement l'accès au microphone sur les origines publiques non sécurisées. Le chat textuel ne nécessite pas l'autorisation du microphone.

Limite entre messages et frame#

Le loader n'accepte que maf:ready, maf:open, maf:close et les messages de cycle de vie du thème associés au slug du site en cours. Les messages entrants de la frame sont vérifiés par rapport à https://makeagent.fast. Ne copiez pas le loader dans votre propre bundle et ne supprimez pas cette validation d'origine.

Le code de la page hôte ne doit pas tenter d'accéder au DOM de l'iframe. La frame est volontairement cross-origin ; la surface d'intégration prise en charge se compose du loader, de ses attributs data-* documentés et des méthodes d'identité ci-dessous.

Secrets et identité des visiteurs#

Le slug du site et l'URL du loader sont publics. Tout le reste doit rester absent du code source de la page :

  • N'ajoutez jamais au snippet une clé API MAF, un jeton OAuth, une clé de fournisseur d'IA, un jeton de connecteur ou un secret de webhook.
  • N'intégrez jamais un secret dans un bundle JavaScript et ne l'exposez pas via NEXT_PUBLIC_*, VITE_* ou des variables d'environnement de navigateur similaires.
  • Utilisez une intégration API côté serveur lorsque votre application doit créer des sites, mettre à jour des agents ou récupérer des données privées de l'espace de travail.
  • Ne placez pas d'adresses e-mail, d'identifiants de compte ou d'autres données de visiteurs dans data-label, data-locale ou les paramètres de requête.

Identifier les clients connectés#

Dans Agent → Actions → Clients connectés, créez un secret et copiez-le lorsqu'il s'affiche. Conservez-le uniquement sur votre serveur sous le nom MAF_SECRET_KEY ; ne le placez jamais dans du code navigateur, des variables d'environnement publiques ou un dépôt. Ce secret d'agent est distinct d'une clé API d'espace de travail. La rotation invalide les anciens jetons et modifie la clé de signature des recherches ; la suppression désactive l'identité vérifiée des clients et les recherches jusqu'à la configuration d'un nouveau secret.

Utilisez l'URL de loader mise à jour https://makeagent.fast/embed.js?v=20261022-open dans votre snippet existant. Les anciennes URL versionnées peuvent rester en cache pendant un an et ne fournissent pas ce SDK. Conservez votre liste d'origines autorisées et vos protections CSP.

Votre serveur authentifié doit émettre le jeton à partir du client présent dans sa propre session. N'acceptez jamais un identifiant client arbitraire provenant du navigateur comme identité à signer. Cette fonction utilitaire s'exécute uniquement sur le serveur :

import { createHmac } from "node:crypto";

export function signCustomerIdentity(customer) {
  const secret = process.env.MAF_SECRET_KEY;
  if (!secret) throw new Error("MAF_SECRET_KEY is required");
  const encode = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
  const now = Math.floor(Date.now() / 1000);
  const header = encode({ alg: "HS256", typ: "JWT" });
  const payload = encode({
    sub: customer.id,
    email: customer.email,
    name: customer.name,
    iat: now,
    exp: now + 3600,
  });
  const body = `${header}.${payload}`;
  const signature = createHmac("sha256", secret).update(body).digest("base64url");
  return `${body}.${signature}`;
}

Exigez l'en-tête alg: "HS256" et typ: "JWT". sub est une chaîne stable et non vide de 128 caractères maximum ; exp est un horodatage Unix entier en secondes, situé dans le futur et au plus 24 heures plus tard. iat, facultatif, est un entier ; email, facultatif, doit être valide et comporter au plus 160 caractères ; name, facultatif, comporte au plus 120 caractères. Le jeton complet doit tenir dans 2 048 caractères. Omettez les claims facultatifs dont vous n'avez pas besoin. Les payloads JWT sont signés, mais pas chiffrés.

Renvoyez uniquement le jeton à cette session de navigateur authentifiée via HTTPS, avec Cache-Control: no-store. Ne le journalisez pas, ne l'ajoutez pas aux URL et ne le stockez pas dans localStorage. Une fois embed.js chargé, transmettez le jeton de cette réponse au widget :

window.MakeAgentFast.identify(token);

Pour une initialisation avant l'exécution du loader, définissez plutôt window.MakeAgentFastSettings = { identityToken: token } dans le bootstrap de votre application. Le loader conserve le dernier jeton en mémoire et le transmet lorsque la frame est prête. Actualisez le jeton depuis votre serveur authentifié avant son expiration et appelez de nouveau identify. Chaque requête de chat l'inclut ; les requêtes de conversation utilisent x-maf-identity. Une identité d'hôte vérifiée ne repose jamais sur un cookie af_xid.

Lorsque votre application déconnecte l'utilisateur, appelez ceci avant d'afficher le chat d'un autre compte, et effacez tout jeton de bootstrap conservé par votre application :

window.MakeAgentFast.logout();

Cela réinitialise l'identité du widget et le cache local des conversations ; cela ne déconnecte pas le client de votre propre application et ne révoque pas un jeton copié. Un sub différent d'un autre client efface également le cache du widget. Les jetons invalides, expirés ou destinés à un autre agent ne peuvent pas accéder à l'historique de ce client connecté et basculent vers le parcours visiteur ordinaire. Utilisez des durées d'expiration courtes et gardez le secret de chaque agent séparé. La répétition côté propriétaire ignore les jetons d'identité ; vérifiez l'isolation sur l'intégration réelle avec deux comptes de test distincts.

Consentement, confidentialité et conservation#

Classez l'intégration conformément à votre politique de confidentialité et de consentement. Si votre gestionnaire de consentement bloque les scripts tiers non essentiels, ne chargez embed.js qu'après le consentement concerné. D'ici là, affichez un lien classique ou un espace réservé désactivé plutôt que de contourner le gestionnaire.

Informez les visiteurs lorsque l'expérience utilise l'IA, l'enregistrement du microphone, la collecte de leads, l'analytique ou un fournisseur de messagerie externe, comme l'exigent votre politique et la législation applicable. Confirmez le processus de conservation et de suppression des conversations de votre site avant le lancement ; déconnecter ou supprimer l'intégration ne supprime pas, à lui seul, les conversations existantes.

Liste de contrôle de sécurité avant le lancement#

  • Le site web du client est déployé, et son agent intégré est activé et testé.
  • Seules les origines parentes exactes et prévues figurent dans la liste d'autorisation.
  • La CSP de l'hôte autorise le script, la frame et la requête d'apparence sans caractères génériques trop larges.
  • Le microphone n'est autorisé que si la voix est activée et a été testée en HTTPS.
  • Aucun identifiant ni aucune valeur privée de visiteur n'apparaît dans le HTML, la sortie du bundle ou les journaux du navigateur.
  • Le comportement du gestionnaire de consentement est testé avant et après consentement.
  • Un snippet copié échoue sur une origine absente de la liste d'autorisation.