Seguridad y orígenes
Solo conexiones Web Chat
El token del widget es el de una conexión del CRM. El backend (WidgetService) solo atiende tokens de una conexión con channelType web y estado connected; el fallback a tokens de tenant legacy fue eliminado. Cualquier otro token provoca un error y el widget no se monta automáticamente. Ver Conexiones.
Whitelist de dominios
isOriginAllowed (backend, connection/helpers/origin.helper.ts) compara el Origin de la request (o, en los endpoints HTTP, el Referer si no hay Origin) contra webConfig.allowedDomains:
- Ambos lados se normalizan a
origin(esquema, host y puerto) connew URL. - Sin
Origin/Referer(por ejemplocurlo llamadas servidor a servidor) se rechaza. - La comprobación aplica a los endpoints públicos del widget y al handshake del socket del chat (se lee
client.handshake.headers.origin).
Para que el widget funcione en un sitio, ese origin debe estar en allowedDomains de la conexión Web Chat.
Origin del CRM fijo
El widget siempre habla con el backend escrito en CRM_ORIGIN. No se deriva del script ni puede sobreescribirse desde el sitio: el anfitrión no elige contra qué CRM apunta.
Identidad
- Con
requiresAuthverdadero, la identidad (externalId,username) la declara el sitio anfitrión desde su sesión. El widget no la verifica criptográficamente: la confianza se apoya en el token y en la whitelist de dominios, por lo que quien controle una página permitida puede declarar cualquierexternalId. - Con
requiresAuthfalso, el visitante es anónimo y el id se guarda enlocalStoragebajo el token. - Los datos opcionales (
email,phone,fullName) se persisten en el Contact; los ausentes se ignoran.
Aislamiento entre sesiones
- Las claves de
localStorageincluyen token yexternalId, de modo que un cambio de cuenta no hereda badge ni posición. destroyWidgetaborta subidas y grabaciones en curso para evitar fugas entre visitantes.- El token viaja en la query string (
?token=) de las requests HTTP, codificado conencodeURIComponent.
Contenido
El cuerpo de los mensajes se arma con nodos de texto; appendRichText solo interpreta el marcador **negrita** (que el backend usa en mensajes de sistema) y nunca usa innerHTML. En cambio, si buttonIcon empieza con < se inserta como HTML (innerHTML): debe provenir del sitio anfitrión, nunca de entrada de usuario.