Skip to content
Usuario

Flujo de autenticacion con cookies

El destino de seguridad para navegador es autenticacion basada en cookies: access token y refresh token viajan en cookies HttpOnly; el frontend no recibe tokens en JSON ni los guarda en storage; las mutaciones usan CSRF; la sesion se hidrata desde /api/auth/session.

  1. Browser pide GET /api/auth/csrf.
  2. Backend emite token CSRF signed double-submit y setea cookie CSRF no HttpOnly.
  3. Login envia credenciales con X-CSRF-Token.
  4. Backend valida payload, rate limit, CSRF y Origin/Referer.
  5. Backend crea sesion, access token corto y refresh token v2.
  6. Backend setea cookies HttpOnly para access/refresh.
  7. Backend no devuelve tokens al navegador.
  8. Frontend llama GET /api/auth/session con withCredentials.
  9. Store/Vuex guarda usuario, rol, permisos, business y tenant solo en runtime.
  10. Axios usa withCredentials: true.
  11. Mutaciones POST, PUT, PATCH, DELETE agregan X-CSRF-Token.
  12. Refresh usa cookie HttpOnly, rota refresh token v2 y renueva cookies.
  13. Logout revoca servidor y expira access, refresh y CSRF cookies.
  14. 401 limpia runtime, CSRF runtime y residuos legacy de storage.
CookieUsoHttpOnlySecureSameSitePathDomainPersistencia
__Host-medsync_atAccess token cortoSiSiLax recomendado same-site/NingunoSession cookie por default
__Host-medsync_rtRefresh token v2 rawSiSiLax recomendado same-site/NingunoSession cookie por default
__Host-medsync_csrfCSRF legible por JSNoSiIgual que auth/NingunoSession cookie por default

Reglas:

  • Access/refresh cookies siempre HttpOnly.
  • CSRF cookie no es HttpOnly porque el frontend debe copiar el token al header.
  • __Host- exige Secure, Path=/ y sin Domain.
  • AUTH_COOKIE_MAX_AGE_MODE=session es el default recomendado.
  • Logout debe limpiar cookies con los mismos atributos de Path, Domain, SameSite y Secure.
EndpointMetodoComportamiento esperadoRiesgo principal
/api/auth/csrfGETEmite token CSRF y cookie CSRF.No imprimir token completo en logs.
/api/auth/loginPOSTRequiere CSRF, setea cookies, JSON tokenless.Login CSRF si se omite bootstrap.
/api/auth/sessionGETDevuelve sesion sin tokens.Exponer datos de mas.
/api/auth/refreshTokenPOSTLee refresh cookie, rota refresh, setea cookies nuevas.Repetir regression production-like.
/api/auth/closePUTRequiere access cookie y CSRF; revoca sesion y limpia cookies.Logout sin CSRF o cookies residuales.
/api/auth/forze-closePUTRequiere auth y CSRF.Accion sensible; auditar uso.
/api/auth/sendOtpPOSTRequiere CSRF preauth y rate limit.Enumeracion/abuso OTP.
/api/auth/validateOtpPOSTRequiere CSRF preauth y rate limit.Fuerza bruta de codigo.
/api/auth/resetPasswordPUTRequiere CSRF preauth, challenge valido e invalida sesiones.Toma de cuenta si secret/OTP falla.

Decision CTO/Product para MVP/productivo inicial:

  • Tenant restricted/suspended/inactive en login hace hard-block.
  • Usuario inactivo/bloqueado en login hace hard-block.
  • No se emite sesion.
  • No se emite access cookie.
  • No se emite refresh cookie.
  • No se exponen datos clinicos.
  • Se mantiene error generico de login para no filtrar detalles innecesarios.

La ruta /tenant-restricted no es el destino del login restricted inicial. Se conserva para sesiones ya existentes que luego detecten tenantOperational.allowed=false, por ejemplo si el tenant cambia de estado durante la sesion o si /api/auth/session hidrata un tenant no operativo.

Backlog futuro: Limited restricted tenant session for billing/self-service UX. No implementar ahora.

Local HTTP no puede probar Secure=true ni __Host- de forma real. Solo se permite para desarrollo controlado.

El modo local normal ahora usa esta configuracion por default mediante npm run dev en backend y npm run serve en frontend. El contrato legacy queda disponible solo con npm run dev:legacy y npm run serve:legacy.

AUTH_COOKIE_MODE=d2
BROWSER_AUTH_TRANSPORT=cookie
AUTH_COOKIE_ACCESS_NAME=medsync_at_dev
AUTH_COOKIE_REFRESH_NAME=medsync_rt_dev
AUTH_CSRF_COOKIE_NAME=medsync_csrf_dev
AUTH_COOKIE_SECURE=false
AUTH_COOKIE_SAMESITE=lax
AUTH_COOKIE_DOMAIN=
AUTH_COOKIE_MAX_AGE_MODE=session
CSRF_ENABLED=true
CORS_CREDENTIALS=true
CORS_ALLOWED_ORIGINS=http://localhost:<frontend-port>
CSRF_ALLOWED_ORIGINS=http://localhost:<frontend-port>
REQUIRE_ACTIVE_SESSION=true
VUE_APP_AUTH_COOKIE_MODE=d2
VUE_APP_BROWSER_AUTH_TRANSPORT=cookie
VUE_APP_CSRF_ENABLED=true
VUE_APP_CORE_URL_API=http://127.0.0.1:3009/
AUTH_COOKIE_MODE=d2
BROWSER_AUTH_TRANSPORT=cookie
AUTH_COOKIE_ACCESS_NAME=__Host-medsync_at
AUTH_COOKIE_REFRESH_NAME=__Host-medsync_rt
AUTH_CSRF_COOKIE_NAME=__Host-medsync_csrf
AUTH_COOKIE_SECURE=true
AUTH_COOKIE_SAMESITE=lax
AUTH_COOKIE_DOMAIN=
AUTH_COOKIE_PATH=/
AUTH_COOKIE_MAX_AGE_MODE=session
CSRF_ENABLED=true
CSRF_TOKEN_SECRET=<secret-manager-path>/csrf-secret
CORS_CREDENTIALS=true
CORS_ALLOWED_ORIGINS=https://app.<dominio>
CSRF_ALLOWED_ORIGINS=https://app.<dominio>
REQUIRE_ACTIVE_SESSION=true

Las pruebas locales ya validan gran parte del contrato, incluido browser real con Playwright. El plan de rollout/rollback ya esta documentado. No actives el modo de cookies en produccion hasta ejecutar la validacion production-like con HTTPS/domain real, confirmar cookies Secure=true, ejecutar reset password invalidation end-to-end y aprobar los controles operativos.