diff --git a/frontend/.env.example b/frontend/.env.example index 88f6bcf..7525f13 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -1,4 +1,11 @@ -# Base URL of the SlpModularCms .NET API (Unit 0 backend). -# The backend must be running with CORS configured to allow this origin -# and to send the httpOnly refresh-token cookie (credentials: include). -VITE_API_BASE_URL=http://localhost:5000 +# Base URL of the SlpModularCms .NET API. +# +# LOCAL DEV (recommended): leave empty and configure the Vite proxy in +# vite.config.ts. The proxy forwards /api/* to the backend so all requests +# stay same-origin — required for the SameSite=Strict refresh-token cookie. +VITE_API_BASE_URL= + +# DIRECT (no proxy): point to the backend URL. CORS must allow this origin +# with credentials, and SameSite may block the cookie on page reload if the +# schemes differ (e.g. http frontend → https backend). +# VITE_API_BASE_URL=https://localhost:7221 diff --git a/frontend/src/lib/config.ts b/frontend/src/lib/config.ts index 83a240a..9e75c80 100644 --- a/frontend/src/lib/config.ts +++ b/frontend/src/lib/config.ts @@ -6,7 +6,8 @@ import { z } from 'zod'; * once and only warns in development — production trusts the build-time env. */ const configSchema = z.object({ - apiBaseUrl: z.string().url(), + // Empty string = use Vite proxy (same-origin); a full URL = direct mode. + apiBaseUrl: z.union([z.literal(''), z.string().url()]), }); export type AppConfig = z.infer; diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 39e8ac2..06c2176 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -14,6 +14,17 @@ export default defineConfig({ }, server: { port: 5173, + proxy: { + // Route all /api calls through the Vite dev server so the browser + // sees a single origin. Without this the refreshToken cookie + // (SameSite=Strict) is not sent from http://localhost to + // https://localhost (different scheme = cross-site in Chrome 89+). + '/api': { + target: 'https://localhost:7221', + changeOrigin: true, + secure: false, // allow self-signed dev cert + }, + }, }, test: { globals: true,