diff --git a/src/Web/autopilot-monitor-web/lib/msalConfig.ts b/src/Web/autopilot-monitor-web/lib/msalConfig.ts index 99dc3679..f8757009 100644 --- a/src/Web/autopilot-monitor-web/lib/msalConfig.ts +++ b/src/Web/autopilot-monitor-web/lib/msalConfig.ts @@ -79,13 +79,17 @@ export const loginRequest: RedirectRequest = { * Scopes for accessing the backend API * IMPORTANT: Backend API must be exposed in Azure AD App Registration with this scope * Format: api:///access_as_user - * For testing, you can also use User.Read but disable signature validation in backend + * + * NEXT_PUBLIC_ENTRA_API_CLIENT_ID lets local dev sign in with the dev app + * registration while requesting a token whose audience is the prod API app + * (the deployed backend only accepts its own audience). Unset in production, + * where one app registration serves as both SPA client and API. */ +const apiAppId = + process.env.NEXT_PUBLIC_ENTRA_API_CLIENT_ID || process.env.NEXT_PUBLIC_ENTRA_CLIENT_ID; + export const apiRequest = { - scopes: [ - // Option 1 (recommended): Use backend API scope after exposing API in Azure AD - `api://${process.env.NEXT_PUBLIC_ENTRA_CLIENT_ID}/access_as_user` - ], + scopes: [`api://${apiAppId}/access_as_user`], }; /** diff --git a/src/Web/autopilot-monitor-web/next.config.ts b/src/Web/autopilot-monitor-web/next.config.ts index cd6aed61..50a4c87c 100644 --- a/src/Web/autopilot-monitor-web/next.config.ts +++ b/src/Web/autopilot-monitor-web/next.config.ts @@ -51,6 +51,17 @@ const nextConfig: NextConfig = { { source: "/roadmap", destination: "/", permanent: false }, ]; }, + async rewrites() { + // Dev-only reverse proxy: with DEV_API_PROXY_TARGET set in .env.local, + // /api/* is forwarded server-side through the Next dev server to the + // deployed backend. The browser stays same-origin, so the prod Function + // App needs no localhost CORS entry. Inactive in production builds. + const target = process.env.DEV_API_PROXY_TARGET; + if (process.env.NODE_ENV !== "development" || !target) { + return []; + } + return [{ source: "/api/:path*", destination: `${target}/api/:path*` }]; + }, async headers() { return [ { @@ -64,7 +75,9 @@ const nextConfig: NextConfig = { key: "Content-Security-Policy", value: [ "default-src 'self'", - "script-src 'self' 'unsafe-inline'", + // Dev-only: next dev serves HMR/react-refresh chunks through eval(); + // production stays strict without 'unsafe-eval'. + `script-src 'self' 'unsafe-inline'${process.env.NODE_ENV === "development" ? " 'unsafe-eval'" : ""}`, "style-src 'self' 'unsafe-inline'", "img-src 'self' data: blob: https://*.tile.openstreetmap.org", "font-src 'self'",