fix(auth): Google Sign-In audience mismatch + remove per-user accent color
Root cause of "Google authentication failed": appsettings.Development.json had Auth:GoogleClientId set to the literal placeholder "CHANGE_ME_GOOGLE_CLIENT_ID" while the frontend's .env.development had a real (already-public, already-committed) client ID -- every Google ID token's audience check failed against the backend's placeholder. Fixed by setting the same real client ID on both sides (a client ID is a public identifier, not a secret, safe to commit -- unlike a client secret). Also enabled Auth:AllowRegistration in dev so the existing Google-first self-serve-signup path (auto-create on unmatched verified email, auto-link on matching verified email -- built during Wave 7) is actually exercisable locally. Wired the previously-missing Auth__MicrosoftClientId / NEXT_PUBLIC_MICROSOFT_CLIENT_ID into docker-compose.yml/.env.example (distinct from the existing MICROSOFT_CLIENT_ID used for Outlook mail linking) -- Microsoft sign-in was never deployable, a leftover gap from when it was built. Fixed a stale env-var name in the Microsoft setup hint copy (still said REACT_APP_*, predates the Next.js migration). Removed the per-user accent color picker entirely: it was purely client-side (localStorage + theme.ts), never touched the backend/DB. theme.ts now hardcodes a single ACCENT constant; themePrefs.ts drops get/set/clearAccentColor; App.tsx and SettingsView.tsx drop the accentColor prop threading. Dead accent-related i18n keys removed from both locales. Consolidated Settings' "Account" tab (duplicated GoogleAuthCard, which already lives on the Profile page) into Profile: moved AuthStatusCard and EmailProviderConnections there alongside the existing Google/ Microsoft auth cards, so identity/account-linking lives in one place. Settings drops from 5 tabs to 4 and its General tab uses a consistent SectionCard layout instead of ad-hoc per-card styling. Verified: dotnet build/test (177/177) and npm build/test (57/57) both green; confirmed live against a running dev server that /auth/config now reports googleEnabled with the corrected client ID, Settings has no accent controls, and Profile shows the consolidated auth section.
This commit is contained in:
@@ -36,7 +36,7 @@ import { api } from "./api";
|
||||
import { resolveCaptureUrl } from "./captureUrl";
|
||||
import { clearAuthClientState, setAuthUserKey } from "./auth";
|
||||
import AppShell, { NavItem } from "./layout/AppShell";
|
||||
import { clearAccentColor, getAccentColor, getThemeModePref, setAccentColor, setThemeModePref, ThemeModePref } from "./themePrefs";
|
||||
import { getThemeModePref, setThemeModePref, ThemeModePref } from "./themePrefs";
|
||||
|
||||
const AddJobModal = lazy(() => import("./components/AddJobModal"));
|
||||
const KanbanBoard = lazy(() => import("./components/KanbanBoard"));
|
||||
@@ -104,7 +104,7 @@ function PageLoader() {
|
||||
return <Box sx={{ p: 4 }}><Typography variant="h6">Loading...</Typography></Box>;
|
||||
}
|
||||
|
||||
function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMode, onThemeModeChange, accentColor, onAccentColorChange, onResetAccentColor }: { jobPageSize: 15 | 20 | 25; setJobPageSize: (n: 15 | 20 | 25) => void; jobColumns: JobTableColumns; setJobColumns: (c: JobTableColumns) => void; themeMode: ThemeModePref; onThemeModeChange: (v: ThemeModePref) => void; accentColor: string; onAccentColorChange: (v: string) => void; onResetAccentColor: () => void; }) {
|
||||
function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMode, onThemeModeChange }: { jobPageSize: 15 | 20 | 25; setJobPageSize: (n: 15 | 20 | 25) => void; jobColumns: JobTableColumns; setJobColumns: (c: JobTableColumns) => void; themeMode: ThemeModePref; onThemeModeChange: (v: ThemeModePref) => void; }) {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const { t } = useI18n();
|
||||
@@ -297,7 +297,7 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
|
||||
<Route path="/admin/users" element={<AdminUsersPage />} />
|
||||
<Route path="/admin/system" element={<AdminSystemPage />} />
|
||||
<Route path="/trash" element={<JobTable refreshToken={refreshToken} pageSize={jobPageSize} onPageSizeChange={setAndPersistPageSize} columns={jobColumns} onColumnsChange={setAndPersistColumns} mode="trash" />} />
|
||||
<Route path="/settings" element={<SettingsView pageSize={jobPageSize} onPageSizeChange={setAndPersistPageSize} columns={jobColumns} onColumnsChange={setAndPersistColumns} themeMode={themeMode} onThemeModeChange={onThemeModeChange} accentColor={accentColor} onAccentColorChange={onAccentColorChange} onResetAccentColor={onResetAccentColor} />} />
|
||||
<Route path="/settings" element={<SettingsView pageSize={jobPageSize} onPageSizeChange={setAndPersistPageSize} columns={jobColumns} onColumnsChange={setAndPersistColumns} themeMode={themeMode} onThemeModeChange={onThemeModeChange} />} />
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
@@ -314,19 +314,16 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
|
||||
export default function App() {
|
||||
const systemPrefersDark = useMediaQuery("(prefers-color-scheme: dark)", { defaultMatches: true, noSsr: true });
|
||||
const [themeMode, setThemeMode] = useState<ThemeModePref>(() => getThemeModePref());
|
||||
const [accentColor, setAccentColorState] = useState<string>(() => getAccentColor());
|
||||
const effectiveMode: "light" | "dark" = themeMode === "light" ? "light" : themeMode === "dark" ? "dark" : systemPrefersDark ? "dark" : "light";
|
||||
const theme = useMemo(() => getTheme(effectiveMode, accentColor), [effectiveMode, accentColor]);
|
||||
const theme = useMemo(() => getTheme(effectiveMode), [effectiveMode]);
|
||||
|
||||
useEffect(() => {
|
||||
const sync = () => { setThemeMode(getThemeModePref()); setAccentColorState(getAccentColor()); };
|
||||
const sync = () => { setThemeMode(getThemeModePref()); };
|
||||
window.addEventListener("auth-changed", sync);
|
||||
return () => window.removeEventListener("auth-changed", sync);
|
||||
}, []);
|
||||
|
||||
const onThemeModeChange = (v: ThemeModePref) => { setThemeModePref(v); setThemeMode(v); };
|
||||
const onAccentColorChange = (v: string) => { setAccentColor(v); setAccentColorState(getAccentColor()); };
|
||||
const onResetAccentColor = () => { clearAccentColor(); setAccentColorState(getAccentColor()); };
|
||||
|
||||
const [jobPageSize, setJobPageSize] = useState<15 | 20 | 25>(() => {
|
||||
const raw = window.localStorage.getItem("jobPageSize");
|
||||
@@ -349,14 +346,14 @@ export default function App() {
|
||||
{ path: "/login", element: <LoginPage />, errorElement: <RouteErrorPage /> },
|
||||
{ path: "/forgot-password", element: <ForgotPasswordPage />, errorElement: <RouteErrorPage /> },
|
||||
{ path: "/reset-password", element: <ResetPasswordPage />, errorElement: <RouteErrorPage /> },
|
||||
{ path: "/*", element: <Shell jobPageSize={jobPageSize} setJobPageSize={setJobPageSize} jobColumns={jobColumns} setJobColumns={setJobColumns} themeMode={themeMode} onThemeModeChange={onThemeModeChange} accentColor={accentColor} onAccentColorChange={onAccentColorChange} onResetAccentColor={onResetAccentColor} />, errorElement: <RouteErrorPage /> },
|
||||
], { future: { v7_relativeSplatPath: true } }), [jobColumns, jobPageSize, themeMode, accentColor]);
|
||||
{ path: "/*", element: <Shell jobPageSize={jobPageSize} setJobPageSize={setJobPageSize} jobColumns={jobColumns} setJobColumns={setJobColumns} themeMode={themeMode} onThemeModeChange={onThemeModeChange} />, errorElement: <RouteErrorPage /> },
|
||||
], { future: { v7_relativeSplatPath: true } }), [jobColumns, jobPageSize, themeMode]);
|
||||
|
||||
return (
|
||||
<ToastProvider>
|
||||
<ConfirmProvider>
|
||||
<PromptProvider>
|
||||
<CssVarsProvider key={`${effectiveMode}:${accentColor}`} theme={theme as any} defaultMode={effectiveMode} disableTransitionOnChange>
|
||||
<CssVarsProvider key={effectiveMode} theme={theme as any} defaultMode={effectiveMode} disableTransitionOnChange>
|
||||
<CssBaseline enableColorScheme />
|
||||
<I18nProvider>
|
||||
<RouterProvider router={router} future={{ v7_startTransition: true }} />
|
||||
|
||||
Reference in New Issue
Block a user