feat(auth): sesión local del CRM (patrón SIWEB) para eliminar el bucle de login
Desacopla la sesión de la app del access token de Keycloak (60s). Tras el SSO/ refresh, el backend emite un JWT de sesión local (HS256) con vida por inactividad (SESSION_IDLE_MINUTES, cap SESSION_MAX_HOURS) y guarda los tokens KC en valkey. La app usa esa sesión local como bearer (cookie access_token); el token KC vive en kc_access_token solo para llamadas directas al Hub. Así el refresh KC contra el Hub solo se intenta al expirar la sesión local, no cada ~60s → se elimina el bucle causado por el bug "Token is not active" del relay. Se RESPETA la revocación central de Keycloak: si el Hub rechaza el refresh, la sesión termina (401). Sin re-emisión de fallback → sin bypass de revocación. Todo detrás de SESSION_STORE_ENABLED (default False = comportamiento idéntico). Backend: core/local_session.py, core/session_store.py (valkey), verify_token acepta la sesión local, refresh la emite/actualiza; DTOs con session_token/session_id; test unitario de local_session. Frontend: access_token=sesión local, kc_access_token para el Hub; sso/refresh/ silent-refresh/switch-tenant y pantallas de workspace cableadas. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,19 @@ class Settings(BaseSettings):
|
||||
PERMISSION_CACHE_ENABLED: bool = True
|
||||
PERMISSION_CACHE_TTL_SECONDS: int = 300
|
||||
|
||||
# Sesión local del CRM (patrón SIWEB) — desacopla la sesión de la app del
|
||||
# token KC de 60s. Tras SSO/login se guardan los tokens KC en valkey y se emite
|
||||
# una sesión local firmada (HS256) con vida por inactividad (idle) y cap
|
||||
# absoluto. Así el refresh del token KC contra el Hub solo se intenta al expirar
|
||||
# la sesión local (no cada ~60s), lo que elimina el bucle de login.
|
||||
#
|
||||
# SE RESPETA la revocación central de Keycloak: si el Hub rechaza el refresh, la
|
||||
# sesión termina (no hay re-emisión local de fallback). Flag-gated para rollback:
|
||||
# con SESSION_STORE_ENABLED=False el comportamiento no cambia.
|
||||
SESSION_STORE_ENABLED: bool = False
|
||||
SESSION_IDLE_MINUTES: int = 30
|
||||
SESSION_MAX_HOURS: int = 10
|
||||
|
||||
# Synchronization
|
||||
SYNC_SECRET_TOKEN: str = "change-this-sync-token-in-production"
|
||||
CENTRAL_SERVER_URL: str = "http://localhost:8000/api/v1/core/help-center/sync/"
|
||||
|
||||
Reference in New Issue
Block a user