Integración FTL Trace ↔ Dolibarr

Acceso al ERP sin segundo login

Desde el dashboard de FTL Trace, un solo click abre Dolibarr ya autenticado: sin escribir credenciales, sin pasar por la pantalla de login del ERP. Sesión válida en menos de un segundo, transparente para el usuario.

✓ Funcionando en dev Test E2E: Playwright Sin modificar Dolibarr Cookie en dominio padre

Overview

El dashboard de FTL Trace ahora ofrece un botón “Ir a ERP” en la barra lateral. Al presionarlo, el ERP se abre en una pestaña nueva con la sesión de la usuaria ya iniciada — el usuario no ve ninguna pantalla intermedia de login.

Esto resuelve un dolor concreto: hasta ahora, cada vez que un usuario quería ir a Dolibarr desde FTL Trace, tenía que recordar y reescribir sus credenciales del ERP. La integración elimina ese paso.

¿Qué se obtiene? Un único punto de partida (el dashboard) desde donde el usuario llega a Dolibarr autenticado. Las credenciales del ERP viven cifradas en el backend; el usuario no las ve ni las escribe.

Beneficios

  • Menos fricción: un click en lugar de tres pasos (cambiar pestaña, ir al ERP, login).
  • Menos errores: ya no hay olvidos de password ni typos.
  • Mejor UX consistente: el dashboard se siente como el punto único de entrada.
  • Auditabilidad: cada apertura del ERP queda registrada en el log del backend.

Cómo lo ve la usuaria

El flujo, desde el momento en que la usuaria está logueada en el dashboard:

  1. Ubicar el botón en la barra lateral En la sección inferior del sidebar — debajo de “Gestión de Usuarios” — aparece la opción Ir a ERP con un ícono de enlace externo.
  2. Click en “Ir a ERP” No se abre un modal ni redirige la pestaña actual: se dispara la apertura de una nueva pestaña.
  3. El backend negocia la sesión con Dolibarr En unos cientos de milisegundos, el backend descifra las credenciales del ERP de la usuaria, hace el login con Dolibarr en su nombre, y obtiene una cookie de sesión válida.
  4. La pestaña nueva muestra Dolibarr ya logueado La usuaria aterriza directamente en la home del ERP — no ve la pantalla de login. Puede operar Dolibarr con normalidad.
  5. El dashboard sigue abierto en la pestaña original No hay pérdida de contexto: la usuaria puede ir y venir entre dashboard y ERP cuantas veces necesite.

Video del flujo

Grabación del recorrido completo, capturada por el test E2E automatizado:

Resolución 1280×720 · Generado por Playwright (revisor/tests/erp-sso.spec.ts).

Casos de borde

¿Qué pasa si la usuaria nunca configuró sus credenciales de Dolibarr?

El backend devuelve HTTP 409 con un mensaje: “No tienes credenciales de Dolibarr configuradas. Configúralas en tu perfil antes de continuar.” El frontend muestra la alerta y no abre la pestaña.

¿Qué pasa si Dolibarr está caído o lento?

El backend tiene timeout de 15 segundos. Si Dolibarr no responde, la nueva pestaña muestra el error HTTP 502 indicando que no se pudo contactar al ERP. La sesión del dashboard sigue intacta.

¿Qué pasa si las credenciales del ERP cambiaron?

Dolibarr rechaza el login y el backend devuelve HTTP 401. La usuaria debe actualizar el password vía PUT /api/v1/dolibarr/credentials (futuro: pantalla de “Mi perfil → Cuenta de Dolibarr”).

¿Y la sesión del ERP cuando la usuaria cierra la pestaña?

La cookie DOLSESSID queda en el navegador hasta que el usuario la limpie o expire por inactividad (configuración propia de Dolibarr). Para forzar cierre, basta con hacer logout dentro del ERP.

Resumen técnico

La integración no requiere cambios en Dolibarr. El backend de FTL Trace actúa como un agente de SSO: hace el login server-side contra el ERP, captura la cookie de sesión y la traslada al navegador del usuario usando una cookie con Domain=.dpp.fintechlab.la — el dominio padre compartido entre todos los apps.

Tres endpoints nuevos en el backend, un botón nuevo en el sidebar del frontend, una tabla nueva en la base de datos. Sin SSO module, sin OAuth, sin cambios en el código del ERP.

Componentes tecnológicos

Por capa, qué se tocó y dónde vive el código:

Backend · Python · FastAPI
Router de Dolibarr

3 endpoints: emisión de token SSO, redirect con login, upsert de credenciales.

  • apps/backend/src/api/routers/dolibarr.py
Backend · Cifrado
Wrapper de Fernet

Cifra/descifra el password de Dolibarr con clave simétrica del entorno.

  • apps/backend/src/infrastructure/dolibarr/crypto.py
Backend · Tokens
SSO Token de un solo uso

HMAC-SHA256, TTL 30s, jti consumibles solo una vez.

  • apps/backend/src/infrastructure/dolibarr/sso_token.py
Frontend · Astro · Sidebar
Entrada de menú + handler

Botón con data-action="dolibarr-sso" e interceptor en el script del sidebar.

  • apps/app-astro-dashboard/src/data/sidebar-menu.ts
  • apps/app-astro-dashboard/src/components/Sidebar.astro
  • apps/app-astro-dashboard/src/scripts/sidebar.ts
Frontend · API SSR
Proxy del JWT

Lee la cookie ftl_access_token en el server-side de Astro y la forwardea como Bearer al backend.

  • apps/app-astro-dashboard/src/pages/api/dolibarr/sso-link.ts
DB · PostgreSQL · SQLModel
Tabla dolibarr_credentials

Una fila por usuario con username + password cifrado en bytes.

  • apps/backend/src/domain/models/dolibarr_credentials.py
  • apps/backend/src/migrations/versions/m9n56b056_*.py
ERP · Dolibarr v22
Sin cambios

El backend habla con el form de login regular (/index.php) — captura el token CSRF del HTML, completa el login, y forwardea la cookie.

  • https://pruebas2.dpp.fintechlab.la
QA · Playwright
Test E2E

Login → click → verifica home del ERP. Graba video.

  • project management/erp-integration/revisor/tests/erp-sso.spec.ts

Flujo técnico

Lo que pasa cuando la usuaria hace click, en orden:

1 — El navegador pide al SSR de Astro un token SSO

Click en a[data-action="dolibarr-sso"] dispara fetch('/api/dolibarr/sso-link', { method: 'POST' }). La cookie ftl_access_token (httpOnly, scope dashboard) viaja con la request porque es same-origin.

2 — El SSR de Astro forwardea como Bearer al backend

El endpoint /api/dolibarr/sso-link en Astro lee la cookie y llama al backend FastAPI con Authorization: Bearer <jwt>. Esto evita que el JWT viaje al JS del browser.

POST /api/v1/dolibarr/sso-link
Authorization: Bearer <JWT>
3 — Backend emite token HMAC de un solo uso

Verifica que la usuaria tenga credenciales de Dolibarr cargadas y emite un token firmado con HMAC-SHA256 (clave DOLIBARR_SSO_SIGNING_KEY, TTL 30s). Devuelve la URL absoluta del redirect:

{ "url": "https://dev-back.dpp.fintechlab.la/api/v1/dolibarr/sso-redirect?t=<token>" }

El frontend abre esa URL en una pestaña nueva con window.open(url, '_blank', 'noopener,noreferrer').

4 — La pestaña nueva golpea /sso-redirect

El backend valida y consume el token (jti único, no se puede reusar). Recupera las credenciales del usuario y descifra el password con Fernet.

5 — Login server-side contra Dolibarr

Con httpx.Client, el backend hace dos requests internos:

  1. GET https://pruebas2.../index.php → captura el cookie inicial DOLSESSID_* y extrae el token CSRF del HTML del form de login (regex sobre <input name="token" value="...">).
  2. POST https://pruebas2.../index.php con username, password, token, actionlogin=login, loginfunction=loginfunction y la cookie del paso 1.

Si la respuesta NO contiene name="password" visible, el login fue exitoso (Dolibarr v22 responde 200 con la home directamente).

6 — Forwardeo de la cookie al navegador

El backend responde con un 302 a la home de Dolibarr y un Set-Cookie con Domain=.dpp.fintechlab.la, lo que permite que el browser envíe esa cookie en la siguiente request a pruebas2.dpp.fintechlab.la:

HTTP/1.1 302 Found
Location: https://pruebas2.dpp.fintechlab.la/index.php?mainmenu=home
Set-Cookie: DOLSESSID_xxx=<valor>; Domain=.dpp.fintechlab.la;
            Path=/; Secure; HttpOnly; SameSite=Lax
7 — Browser sigue el redirect; Dolibarr lee la cookie y muestra la home

Como el browser ahora tiene la cookie con scope .dpp.fintechlab.la, la envía automáticamente a pruebas2.dpp.fintechlab.la. Dolibarr la valida contra su sesión activa y renderiza la home. Para el usuario, todo transcurre en una sola navegación que dura ~1s.

Seguridad

Cifrado del password de Dolibarr

El password se guarda cifrado con Fernet (AES-128-CBC + HMAC-SHA256 autenticado). La clave (DOLIBARR_FERNET_KEY) vive solo en el entorno del backend; ni el frontend ni la BD tienen acceso al password en claro.

Si la clave rota, los registros previos quedan inválidos hasta que el usuario re-setee su password con la nueva clave activa.

Token SSO de un solo uso (anti-replay)

El token entre /sso-link y /sso-redirect se firma con HMAC-SHA256, vive 30 segundos, y se invalida tras el primer uso (set en memoria de jti consumidos). Esto bloquea reutilización aunque alguien capture la URL del redirect.

Limitación conocida: el set de jti vive en memoria del proceso. Con multi-worker hay que migrarlo a Redis.

JWT del dashboard nunca expone al JS del browser

La cookie ftl_access_token es httpOnly; el SSR de Astro la lee server-side y la forwardea al backend como Bearer. El JS del navegador no tiene acceso al token.

El password viaja solo server-to-server

A diferencia de la primera idea (form auto-submit con credenciales en el HTML), el password de Dolibarr nunca aterriza en el navegador. Se mueve únicamente entre el backend de FTL Trace y el servidor de Dolibarr.

Cookie con SameSite=Lax + Secure + HttpOnly

La cookie DOLSESSID que se forwardea al browser tiene:

AtributoValorPor qué
Domain.dpp.fintechlab.laCompartir entre subdominios del proyecto
SecuretrueSolo HTTPS
HttpOnlytrueJS no puede leerla
SameSiteLaxPermite navegación top-level same-site

Configuración

Variables de entorno (backend)

VariableEjemploNotas
DOLIBARR_BASE_URLhttps://pruebas2.dpp.fintechlab.laSin slash final
DOLIBARR_FERNET_KEY<32 bytes b64url>Fernet.generate_key()
DOLIBARR_SSO_SIGNING_KEY<random 48+ chars>secrets.token_urlsafe(48)
DOLIBARR_SSO_TOKEN_TTL_SECONDS30Default 30s
DOLIBARR_COOKIE_DOMAIN.dpp.fintechlab.laDominio padre compartido

Seedeo de credenciales (admin)

Por usuario, una sola vez:

PUT /api/v1/dolibarr/credentials
Authorization: Bearer <JWT del usuario>
Content-Type: application/json

{ "dolibarr_username": "jllanos", "password": "..." }

Test E2E (Playwright)

El test del directorio revisor/ automatiza el flujo y graba video.

cd "project management/erp-integration/revisor"
npm install
npm run install:browsers
cp .env.example .env   # completar DASHBOARD_PASSWORD
npm test

Salidas:

  • test-results/<test>-chromium/video.webm — flujo completo grabado.
  • test-results/dolibarr-home-logged-in.png — screenshot final.
  • playwright-report/index.html — steps + traces.

Issues conocidos / Próximos pasos

UI para que el usuario configure su password de Dolibarr

Hoy las credenciales se cargan vía PUT /credentials manualmente. Falta una pantalla de “Mi cuenta → Cuenta de Dolibarr” en el dashboard.

Multi-worker: jti consumibles en memoria

El set in-memory de tokens consumidos no es seguro entre procesos. Migrar a Redis cuando se escale a más de un worker.

Cookies host-only previas en Dolibarr

Si un usuario YA tenía una cookie DOLSESSID host-only en pruebas2.dpp.fintechlab.la de visitas anteriores, puede coexistir con la cookie de dominio padre y confundir a PHP. Mitigación: probar en ventana incógnita o limpiar cookies del ERP.

Frágil al markup del login de Dolibarr

El backend extrae el token CSRF con regex sobre el HTML. Si Dolibarr cambia el orden de atributos o el nombre del campo en una upgrade futura, hay que ajustar _TOKEN_RE en apps/backend/src/api/routers/dolibarr.py.