From 46e054f5dd3c1e2d26b03f3a7bb6c3e4d7f475fc Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Tue, 24 Mar 2026 09:51:38 -0400 Subject: [PATCH] feat: Introduce core backend application with authentication API and a new popout HTML page. --- backend/auth/router.py | 24 ++++++++++++++++++++++++ backend/main.py | 6 +++--- frontend/popout.html | 4 +++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/backend/auth/router.py b/backend/auth/router.py index 732a8ed..e5a3fb3 100644 --- a/backend/auth/router.py +++ b/backend/auth/router.py @@ -138,6 +138,17 @@ async def login(request: LoginRequest, response: Response): logger.info(f"User '{request.username}' logged in") + # Set access token as cookie for same-origin requests (e.g. popout window) + response.set_cookie( + key="access_token", + value=access_token, + max_age=ACCESS_TOKEN_EXPIRE_SECONDS, + httponly=True, + samesite="lax", + secure=secure, + path="/", + ) + return { "access_token": access_token, "token_type": "bearer", @@ -174,6 +185,19 @@ async def refresh_token_endpoint(request: Request, response: Response): new_access_token = create_access_token(user) + # Update cookies + import os + secure = os.environ.get("OBSIGATE_SECURE_COOKIES", "false").lower() == "true" + response.set_cookie( + key="access_token", + value=new_access_token, + max_age=ACCESS_TOKEN_EXPIRE_SECONDS, + httponly=True, + samesite="lax", + secure=secure, + path="/", + ) + return { "access_token": new_access_token, "token_type": "bearer", diff --git a/backend/main.py b/backend/main.py index 6e53ec1..b66c189 100644 --- a/backend/main.py +++ b/backend/main.py @@ -381,10 +381,10 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware): response.headers["Content-Security-Policy"] = ( "default-src 'self'; " "script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://unpkg.com https://esm.sh; " - "style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; " + "style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://fonts.googleapis.com; " "img-src 'self' data: blob:; " - "connect-src 'self'; " - "font-src 'self';" + "connect-src 'self' https://esm.sh https://unpkg.com; " + "font-src 'self' https://fonts.gstatic.com;" ) return response diff --git a/frontend/popout.html b/frontend/popout.html index f755876..b9b6cd6 100644 --- a/frontend/popout.html +++ b/frontend/popout.html @@ -109,7 +109,9 @@ document.getElementById('file-title').textContent = path.split('/').pop(); try { - const response = await fetch(`/api/file/${encodeURIComponent(vault)}?path=${encodeURIComponent(path)}`); + const response = await fetch(`/api/file/${encodeURIComponent(vault)}?path=${encodeURIComponent(path)}`, { + credentials: 'include' + }); if (!response.ok) throw new Error("Erreur lors du chargement du fichier"); const data = await response.json();