5.1 KiB
5.1 KiB
Frontend Auth And Company Selection
Runtime actual
El frontend ERP usa el runtime nuevo:
@erp/identity/client
IdentityAuthSessionProvider
DataSourceProvider
Axios compartido
No debe usarse @erp/auth/client como runtime nuevo.
Flujo actual
login
-> GET /identity/auth/session
-> GET /companies/available
-> resolver empresa activa
-> auto-selección si hay una sola empresa
-> selector si hay varias
-> /no-companies si no hay empresas
-> X-Company-Id en rutas tenant-scoped
Login
El login usa:
POST /identity/auth/login
Tras login correcto:
- se guardan
accessTokenyrefreshToken - se limpia cualquier
activeCompanyIdprevio - se carga
GET /companies/available - se resuelve el redirect autenticado según companies disponibles
Session restore
Si existe accessToken persistido:
- se llama
GET /identity/auth/session - se hidrata la sesión autenticada
- se llama
GET /companies/available - se resuelve
activeCompanyIdpersistido o auto-selección
Si la restauración falla:
- se limpia la sesión
- se limpia
activeCompanyId
Selección de empresa
Cero empresas
Si companies.length === 0:
- se muestra
/no-companies - no existe
activeCompanyId - no se envía
X-Company-Id - sigue disponible el logout
Una empresa
Si companies.length === 1:
- se selecciona automáticamente
- se guarda
activeCompanyId - no se muestra
/company-selection - se continúa al área privada
Varias empresas
Si companies.length > 1:
- se muestra
/company-selection - no existe
activeCompanyIdhasta elegir - el usuario selecciona company
- se guarda
activeCompanyId - se continúa al área privada
activeCompanyId persistido ya no disponible
Si el activeCompanyId persistido ya no aparece en GET /companies/available:
- con
0companies ->/no-companies - con
1company -> auto-selección de la disponible - con varias companies ->
/company-selection
GET /companies/available
Endpoint actual:
GET /companies/available
Authorization: Bearer <access_token>
No requiere:
X-Company-Id
No usa:
requireIdentityTenant(params)
Devuelve:
export type AvailableCompaniesResponseDTO = {
companies: AvailableCompanyDTO[];
};
App company switcher
Componente documentado:
apps/web/src/layout/app-company-switcher.tsx
Propósito:
- cambiar de empresa activa una vez iniciada la sesión
- mostrar la empresa activa actual dentro del layout autenticado
Reglas:
- consume
availableCompaniesyactiveCompanydesdeuseIdentityAuthSession() - usa
changeActiveCompany()oselectActiveCompany()del contexto, no requests directas - no llama directamente a
GET /companies/availablesi el contexto ya está hidratado - no maneja tokens
- no usa
@erp/auth/client - no usa
companySlugpara autenticación - no modifica el access token
- al cambiar empresa, las siguientes requests tenant-scoped deben salir con el nuevo
X-Company-Id
Comportamiento esperado:
0empresas: no rompe; render deshabilitado o equivalente1empresa: muestra la empresa activa; no hace falta selector operativoNempresas: permite cambiar entre las permitidas y marca la activa
Headers
No deben llevar X-Company-Id
POST /identity/auth/login
POST /identity/auth/refresh
POST /identity/auth/logout
GET /identity/auth/session
GET /companies/available
Sí deben llevar X-Company-Id
Rutas tenant-scoped como:
/customers/catalogs/*/customer-invoices/*/factuges
siempre que exista activeCompanyId.
Refresh automático sobre 401
El frontend implementa refresh automático global sobre Axios.
Comportamiento:
- una request autenticada recibe
401 - si existe
refreshToken, se llamaPOST /identity/auth/refresh - se guardan los nuevos tokens
- se reintenta una única vez la request original
- si refresh falla, se limpia la sesión y se redirige a
/login
Reglas implementadas
- retry único por request con
_retry - refresh concurrente único con
refreshPromisecompartida - varias requests
401esperan el mismo refresh - login
401no dispara refresh - refresh
401no intenta refrescarse a sí mismo /identity/auth/refreshno llevaX-Company-Id- la request tenant-scoped reintentada conserva
X-Company-Id
Endpoints excluidos de tenant header y refresh
/identity/auth/login
/identity/auth/refresh
/identity/auth/logout
/identity/auth/session
/companies/available
Pruebas manuales recomendadas
- Login con usuario sin empresas: debe ir a
/no-companies. - Login con usuario con una empresa: debe auto-seleccionarse y entrar al área privada.
- Login con usuario con varias empresas: debe mostrarse
/company-selection. - Cambio de empresa desde
app-company-switcher: la request tenant-scoped siguiente debe llevar el nuevoX-Company-Id. - Access token expirado con refresh válido: debe ejecutarse refresh + retry único.
- Refresh token inválido: debe limpiarse la sesión y redirigir a
/login. - Endpoints auth y
GET /companies/available: no deben llevarX-Company-Id. - Rutas tenant-scoped: deben llevar
X-Company-Idcuando existaactiveCompanyId.