Skip to main content

Modo iframe (Frame Bridge)

El CRM puede incrustarse en otra aplicación mediante un iframe y autenticarse por postMessage (SSO), sin pasar por la pantalla de login. La detección y el puente están en dos servicios de core/services/ui.

Detección​

IframeDetectionService.isIframe() devuelve window.self !== window.top, calculado una sola vez al instanciarse.

Protocolo postMessage​

FrameBridgeService.init() (llamado desde el constructor de AuthEffects) solo actúa en iframe: registra el listener message y envía { type: 'CRM_READY' } al padre con window.parent.postMessage(..., '*').

Mensajes entrantes (padre → CRM):

typeContenidoEfecto
CRM_AUTHtoken (token SSO del tenant) y data (externalId, email?, username?, firstname?, lastName?, userType?, roleId?)Despacha frameAuthenticateRequest → POST /auth/frame-login
CRM_NAVIGATEto (ruta)Navega solo si ya hay sesión (_authenticated), y responde CRM_NAVIGATED

Si environment.allowedParentOrigins tiene elementos, los mensajes cuyo event.origin no esté incluido se ignoran. Si el arreglo está vacío no se filtra el origen.

Mensajes salientes (CRM → padre), tipo FrameOutgoingEventType: CRM_AUTHENTICATED, CRM_READY, CRM_CHAT_OPENED, CRM_MESSAGE_SENT, CRM_CHAT_CLOSED, CRM_AUTH_EXPIRED, CRM_NAVIGATED. En el código revisado solo se emiten CRM_READY, CRM_AUTHENTICATED, CRM_NAVIGATED y CRM_AUTH_EXPIRED.

Flujo​

  1. El iframe carga; AuthGuard deja pasar la ruta aunque no haya sesión (isIframe()), y AuthTokenInterceptor no redirige a login.
  2. El CRM emite CRM_READY; el padre responde CRM_AUTH.
  3. frameLogin$ obtiene el token (/auth/frame-login, con header skip), carga get-me, guarda la sesión, navega a /whaticket/chat y emite CRM_AUTHENTICATED.
  4. Si el login falla o una petición devuelve 401, se navega a /auth/reconnect; el botón de esa pantalla emite CRM_AUTH_EXPIRED para que el padre reenvíe CRM_AUTH.

Seguridad​

  • Los mensajes salientes usan targetOrigin: '*'; solo llevan tipo y datos de navegación, no el token de sesión.
  • La validación de origen entrante depende de environment.allowedParentOrigins; ver Entornos.
  • El tenant token del padre se valida en el backend; ver Auth.