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.
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:
- 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.
- 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.
- 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.
- 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.
- 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:
Router de Dolibarr
3 endpoints: emisión de token SSO, redirect con login, upsert de credenciales.
- apps/backend/src/api/routers/dolibarr.py
Wrapper de Fernet
Cifra/descifra el password de Dolibarr con clave simétrica del entorno.
- apps/backend/src/infrastructure/dolibarr/crypto.py
SSO Token de un solo uso
HMAC-SHA256, TTL 30s, jti consumibles solo una vez.
- apps/backend/src/infrastructure/dolibarr/sso_token.py
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
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
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
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
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:
- GET
https://pruebas2.../index.php→ captura el cookie inicialDOLSESSID_*y extrae el token CSRF del HTML del form de login (regex sobre<input name="token" value="...">). - POST
https://pruebas2.../index.phpconusername,password,token,actionlogin=login,loginfunction=loginfunctiony 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:
| Atributo | Valor | Por qué |
|---|---|---|
Domain | .dpp.fintechlab.la | Compartir entre subdominios del proyecto |
Secure | true | Solo HTTPS |
HttpOnly | true | JS no puede leerla |
SameSite | Lax | Permite navegación top-level same-site |
Configuración
Variables de entorno (backend)
| Variable | Ejemplo | Notas |
|---|---|---|
DOLIBARR_BASE_URL | https://pruebas2.dpp.fintechlab.la | Sin 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_SECONDS | 30 | Default 30s |
DOLIBARR_COOKIE_DOMAIN | .dpp.fintechlab.la | Dominio 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.