# Auth Integration ## Purpose The product frontend authenticates through backend-owned session cookies. The backend transport details are documented in `backend/docs/cookie-auth.md`. ## Runtime Configuration The frontend reads only public browser-safe API configuration from: - `VITE_BACKEND_API_URL` Local values live in ignored `frontend/.env` files; the template value is documented in `frontend/.env.example`. Do not add secrets to frontend env files. Vite exposes `VITE_*` values to the browser bundle. ## Auth Flow 1. `AuthContext` delegates auth state to `useAuthSession` from `frontend/src/business/auth/hooks.ts`. 2. `useAuthSession.signIn` calls `POST /api/auth/signin/local` through `frontend/src/shared/api/auth.ts`. 3. The backend sets an HttpOnly auth cookie and returns the current user profile. 4. `useAuthSession` restores the session with `GET /api/auth/me`. 5. The backend returns the current product profile, including `productRole`, `campus`, `staffProfile`, and `permissions`. 6. UI-facing `StaffProfile` is derived in `frontend/src/business/auth/mappers.ts`. 7. `useAuthSession.signOut` calls `POST /api/auth/signout`; the backend clears the auth cookie. 8. `SignInModal` delegates modal mode, form draft state, validation, and submit workflow to `useAuthModalWorkflow`. ## Refresh Tokens The refresh flow keeps tokens backend-owned: 1. Backend sign-in sets short-lived access and long-lived refresh HttpOnly cookies. 2. Protected API requests use the access cookie only. 3. `POST /api/auth/refresh` uses the refresh cookie only, rotates it server-side, sets fresh cookies, and returns the current user profile. 4. `httpClient` performs one controlled refresh-and-retry after an access-expiry `401`. 5. If refresh fails because both access and refresh credentials are expired or invalid, the business layer clears the user and redirects to `/login`. 6. Non-auth backend failures remain observable errors; no infinite retry and no silent fallback. The frontend must not read, store, or receive access or refresh token values. ## Login Route The app exposes `/login` as the deterministic destination for expired sessions. Sign-in also remains available as a modal for in-app guest prompts. Rules: - `/login` must reuse the existing auth business hook and API functions. - Auth-expired redirects must use `replace: true`. - Safe return paths may be preserved only for same-origin product routes. - Tokens and raw session failure details must never be placed in the URL. - Expired access plus valid refresh must restore the session without redirecting. - Expired access plus expired refresh must redirect to `/login` without showing a raw error. ## Layering - View/provider: `frontend/src/contexts/AuthContext.tsx`, `frontend/src/components/frameworks/SignInModal.tsx`, and `frontend/src/components/sign-in-modal/` - Business logic: `frontend/src/business/auth/` - API/data access: `frontend/src/shared/api/auth.ts` - Backend contract types: `frontend/src/shared/types/auth.ts` ## Deferred Product Onboarding Registration, company creation, campus creation, user creation, staff profile creation, and profile updates are intentionally deferred. The backend has generated auth signup/profile endpoints, but the customer has not approved the product workflow for creating companies, campuses, users, role assignments, campus assignments, and staff profiles. Rules: - Do not implement frontend registration or profile creation flows until the backend product contract is defined. - Do not treat generated auth signup/profile endpoints as the product onboarding contract. - Track the cross-application onboarding task in `docs/full-integration-refactor-plan.md`. - New persisted workflows must use typed backend API modules and business-layer hooks. ## Standards - Do not duplicate backend role mapping in the frontend. - Do not add frontend secrets. - Do not store auth tokens in frontend browser storage. - Do not expose auth tokens in URLs or API responses. - Do not add frontend refresh-token storage; refresh uses only backend-owned HttpOnly cookies. - New persisted workflows must use `frontend/src/shared/api/` through `frontend/src/business//`. - New server state should use business-layer hooks built on top of shared API modules.