Skip to content

feat(auth): add backend-managed Firebase session authentication - #8

Open
niluksha wants to merge 14 commits into
stagingfrom
feat/firebase-session-auth
Open

feat(auth): add backend-managed Firebase session authentication#8
niluksha wants to merge 14 commits into
stagingfrom
feat/firebase-session-auth

Conversation

@niluksha

Copy link
Copy Markdown
Collaborator

Summary

Replace the frontend-managed custom password-hash authentication flow with a backend-managed Firebase Authentication session design.

React now communicates only with the Node API. Node validates credentials through Firebase, exchanges Firebase ID tokens for secure session cookies, verifies sessions on protected requests, and performs Firebase/Firestore operations on behalf of authenticated users.

This PR includes implementation Chunks 0–8. The legacy backend password-hash endpoints remain temporarily available until the new authentication flow passes hosted staging and production verification.

What changed

Backend authentication

  • Added environment loading and startup validation.
  • Added reusable Firebase Admin initialization.
  • Added Firebase email/password authentication through the supported REST API.
  • Added Firebase ID-token exchange for HttpOnly session cookies.
  • Added session expiration and configurable warning timestamps.
  • Added revocation checking on every protected request.
  • Added:
    • POST /api/auth/register
    • POST /api/auth/login
    • POST /api/auth/logout
    • GET /api/auth/session
    • GET /api/auth/csrf
  • Added safe authentication logging that excludes passwords, tokens, cookies, CSRF values, and request bodies.

CSRF and cookie security

  • Added signed HMAC-based CSRF tokens.
  • Bound CSRF tokens to the current browser or Firebase session.
  • Added exact Origin validation and JSON content-type validation.
  • Added CSRF protection to authentication mutations and scouting writes.
  • Configured production cookies as:
    • HttpOnly
    • Secure
    • SameSite=Lax
    • Path=/
  • Kept Express as the single owner of API CORS headers.

Frontend authentication

  • Added a centralized credentialed API client.
  • Added verified authentication context and protected routes.
  • Migrated login, registration, logout, and session restoration to the Node API.
  • Removed frontend Firebase SDK authentication and custom-token handling.
  • Removed readable user and uid authentication cookies.
  • Added configurable session-expiration warnings.
  • Added in-place reauthentication so an active scouting form is not discarded.
  • Limited automatic retries to two and avoided retrying uncertain mutations.

Scouting authorization

  • Protected /api/read and /api/write with verified Firebase sessions.
  • Added CSRF protection to /api/write.
  • Derive scoutUid, scoutName, and submittedAt from the verified server session.
  • Discard caller-supplied identity, timestamp, role, and debug fields.
  • Retained the generic /read and /write API temporarily; purpose-specific endpoints remain future work.

Debug authorization

  • Replaced the public debug UID list with a verified Firebase debug custom claim.
  • Added a restricted administration script for granting or removing the claim.
  • Revoke existing sessions when the debug claim changes.
  • Removed the public /api/debug endpoint.
  • Retained the existing synthetic seed feature unchanged for later redesign.

Dependencies and tests

  • Migrated to modular Firebase Admin 14.
  • Updated compatible dependencies.
  • Removed unused dependencies, including cors.
  • Added backend unit and HTTP integration tests.
  • Added Vitest, jsdom, and React Testing Library frontend tests.
  • Recorded the existing frontend lint baseline separately.

Vercel deployment preparation

  • Separated Express application construction from the local Node listener.
  • Added one catch-all Vercel Function for /api/*.
  • Consolidated build and routing settings in the root vercel.json.
  • Configured the frontend production API base as /api.
  • Added the same-origin production configuration.
  • Removed the duplicate frontend/vercel.json.
  • Documented two Vercel projects:
    • mainsim-city-scouting
    • stagingsim-city-scouting-staging
  • Documented that hosted staging uses the development Firebase project with a separate service-account key and CSRF secret.
  • Deferred WAF enforcement until normal shared-IP traffic can be observed.

Verification

  • Backend test suite: 122 tests passed
  • Frontend test suite: 19 tests passed
  • Production frontend build passed
  • Frontend dependency audit reports zero vulnerabilities
  • Root audit has no critical or high-severity findings
  • Six known moderate Firebase transitive findings remain documented
  • Frontend lint remains at the documented baseline of 21 errors and zero warnings
  • Deployment configuration tests passed
  • No credentials or environment secrets are included in the commit

Staging deployment after merge

  1. Connect the staging branch to the sim-city-scouting-staging Vercel project.
  2. Configure the project from the repository root with the Other framework preset.
  3. Add the Production-scoped staging environment variables documented in docs/deployment-setup.md.
  4. Use:
    • the existing development Firebase project;
    • a separate staging service-account key;
    • a staging-only CSRF secret;
    • CORS_ALLOWED_ORIGIN=https://sim-city-scouting-staging.vercel.app;
    • VITE_API_BASE_URL=/api.
  5. Deploy and complete the documented staging smoke checklist.
  6. Confirm registration, login, session restoration, protected writes, CSRF rejection, logout, direct SPA routes, Firestore isolation, and safe logs.

Intentional follow-up work

The following items are intentionally not included in this PR:

  • Removing the legacy /api/login and /api/register password-hash endpoints
  • Deleting the obsolete Firestore auth collection
  • Recreating production Firebase Authentication users
  • Replacing generic /api/read and /api/write
  • Repairing or replacing the synthetic seed feature
  • Adding password reset
  • Adding Playwright
  • Enabling a Vercel WAF rate threshold
  • Splitting the frontend and backend into separate repositories

The legacy authentication implementation will be removed in Chunk 9 only after staging and production verification succeeds. No Firebase or Firestore data is deleted by this PR.

Documentation

  • docs/proposals/firebase-session-authentication.md
  • docs/deployment-setup.md
  • docs/technical-debt/frontend-lint-baseline.md
  • TECHNICAL_DOCUMENTATION.md
  • README.md

Niluksha Wickramaarachchi added 10 commits July 17, 2026 19:49
- load backend configuration from .env.development or .env.production
  based on NODE_ENV, with .env retained as an optional fallback
- add separate development and production npm scripts
- make the backend port configurable through PORT
- replace the hard-coded frontend origin with CORS_ALLOWED_ORIGIN
- validate required backend configuration during startup
- centralize the frontend API base URL using VITE_API_BASE_URL
- add sanitized development and production environment templates
- update Git ignore rules to protect real environment files while
  retaining example files
- remove plaintext login and registration request logging
- remove password-hash logging from the backend and frontend
- remove response logging that could expose authentication tokens
- avoid logging Firestore write bodies containing sensitive data
Move environment-file loading and backend configuration validation into a dedicated, documented config module while preserving the existing file precedence, port validation, and CORS origin requirements.

Centralize Firebase Admin setup in an idempotent initializer that exposes Authentication and Firestore services without logging service-account credentials. Update the existing server routes to use those services without changing their validation, response, or business behavior.

Add Node built-in tests for valid and invalid configuration, development defaults, malformed service-account JSON, and single Firebase initialization through an isolated test double. Expose the suite through npm run test:backend.
Add validated Firebase Web API key, session duration, expiration warning, and cookie policy configuration. Require positive whole-minute durations, ensure the warning precedes expiration, and fail production startup unless session cookies are secure.

Introduce an isolated Firebase Authentication REST client that verifies email and password credentials, returns only the ID token and safe user metadata, discards refresh tokens, and maps Firebase and network failures into safe categories without exposing upstream payloads.

Add documented session helpers for creating Firebase session cookies, verifying them with revocation checks, calculating expiration and warning timestamps, and producing consistent set and clear cookie options.

Update development and production environment examples and align the authentication proposal with the implemented dependency and security decisions. Add Node test coverage for configuration boundaries, REST requests and error mapping, malformed responses, refresh-token exclusion, session timing, cookie policies, and revocation checking.
Add parallel register, login, logout, and current-session endpoints under /api/auth while leaving the legacy authentication, scouting, and debug route implementations unchanged.

Validate required registration and login inputs, preserve passwords exactly, create and verify Firebase session cookies with revocation checks, and return one consistent session representation containing verified identity, debug status, expiration, and warning timestamps. Keep newly created users when automatic session setup fails and map expected Firebase failures to safe HTTP responses.

Use cookie-parser for request-cookie handling and emit minimal structured authentication logs without request bodies, credentials, tokens, cookies, email addresses, or raw Firebase errors. Keep logout idempotent and enforce the configured HttpOnly, Secure, SameSite, path, and lifetime options.

Add Supertest HTTP integration coverage for success paths, validation, Firebase Admin errors, partial registration failure, credential privacy, rate limiting, cookie creation and clearing, missing sessions, custom claims, expiration, revocation, and disabled users.

Align the authentication proposal with the implemented API contract and record password reset as a separately reviewed design and implementation chunk.
Add dependency security remediation as authentication implementation Chunk 4 and renumber subsequent chunks and code references.

Remove the unused Firebase client SDK from both projects, remove unused frontend dotenv, move nodemon to development dependencies, and configure Node.js 22 for consistent local and Vercel runtimes.

Upgrade Firebase Admin to 14.2 and migrate initialization, service access, tests, and JSDoc types from the removed namespace API to the supported modular app, auth, and Firestore entry points.

Upgrade React Router and Vite within their existing major versions and apply compatible non-forced backend and frontend security updates. Frontend audits are clean; backend audits contain no critical or high findings, with the remaining six moderate uuid findings documented as an upstream Google Cloud Storage exception.

Record the unchanged frontend lint baseline in a dedicated technical-debt document with rule and file breakdowns, remediation guidance, and completion criteria. Verify clean lockfile installs, all 75 backend tests, the frontend production build, and API smoke checks.
Implement an HMAC-signed double-submit CSRF flow for the backend-managed Firebase session API.

- Add pre-authentication and session-bound CSRF token issuance with timing-safe validation.

- Protect registration, login, and logout with exact Origin checks and appropriate JSON enforcement.

- Rotate and clear CSRF cookies when the authentication binding changes.

- Validate a dedicated 32-byte hexadecimal CSRF secret and canonical CORS origin at startup.

- Enable credentialed CORS requests with the X-CSRF-Token header.

- Add safe structured rejection logging without exposing credentials, cookies, origins, or token values.

- Cover signing, malformed and forged tokens, browser-style requests, binding rotation, and cookie cleanup.

- Align the authentication proposal, environment templates, and technical documentation through Chunk 5.
Replace the frontend's custom password-hash authentication flow with the Node API session-cookie contract introduced by the authentication proposal.

- add a centralized API client with credentialed requests, in-memory CSRF handling, safe response parsing, and bounded retry behavior
- add React authentication state, startup session restoration, login, registration, logout, session warnings, and in-place reauthentication
- protect authenticated routes and require a fresh session before starting match or pit scouting after the warning threshold
- migrate scouting reads and writes to the shared API client while preserving existing paths, payloads, validation, and local draft behavior
- remove browser-side password hashing, legacy auth document writes, and readable authentication cookies
- add Vitest and React Testing Library coverage for API retries, CSRF rotation, authentication lifecycle, page behavior, and session expiration
- update the proposal, technical documentation, and frontend lint baseline to reflect the implemented Chunk 6 design
Make the verified Firebase session the security and attribution boundary for generic scouting reads and writes while preserving their existing paths and merge behavior.

- require non-revoked Firebase sessions for /api/read and /api/write
- require signed, session-bound CSRF protection for Firestore writes
- discard browser-controlled identity, role, debug, and timestamp fields
- add verified scoutUid, scoutName, and submittedAt values to scouting records while leaving datas/data unchanged
- add safe structured data-route failures without logging request bodies or Firebase details
- add a restricted debug-claim administration command that preserves unrelated claims and revokes existing sessions
- remove the obsolete public debug UID-list endpoint and empty frontend debug module
- retain the known-buggy synthetic seed tool for later purpose-specific API redesign
- cover session rejection, spoof prevention, custom-claim administration, and unchanged mutation replay after reauthentication
- update the proposal, technical documentation, README, and lint baseline with the agreed Chunk 7 decisions
Prepare the combined React and Node application for same-origin deployment on Vercel Hobby.

- Separate Express application construction from the local Node listener and expose it through one catch-all Vercel Function.

- Consolidate frontend and API deployment settings in the root vercel.json, build frontend/dist, and retain the React SPA fallback.

- Configure relative /api browser requests and the approved production origin while keeping Express as the sole CORS header owner.

- Remove the duplicate frontend Vercel configuration and unused cors dependency.

- Add tests for routing, build settings, production cookie configuration, and environment examples.

- Document the main production branch and dedicated staging branch/project topology.

- Record that hosted staging shares the development Firebase project but uses separate service-account and CSRF credentials.

- Defer WAF enforcement pending observed shared-IP traffic and add staging and production smoke-test instructions.
@niluksha
niluksha requested review from dansenchukov and omada15 July 18, 2026 07:48
Update the backend startup log to identify the Sim City Scouting API explicitly. This behavior-neutral change also provides a small commit for validating the staging Vercel deployment configuration.
@vercel

vercel Bot commented Jul 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sim-city-scouting-staging Ready Ready Preview, Comment Jul 20, 2026 6:11pm

Exclude /api and all nested API paths from the React SPA fallback so requests reach the catch-all Express Vercel Function instead of returning index.html.

Update the deployment configuration test to lock in the API-first routing behavior and prevent future catch-all rewrites from shadowing backend endpoints.
Replace the dynamic API function filename with a concrete api/index.js entry point and explicitly route /api requests to it before applying the React SPA fallback.

Temporarily pin Firebase Admin to 13.6.0 so Vercel uses the CommonJS-compatible jwks-rsa 3 and jose 4 dependency chain instead of failing to load Firebase Admin 14 with ERR_REQUIRE_ESM.

Add deployment regression coverage for the function entry point, routing order, SPA exclusion, and compatibility pin. Refresh the lockfile and document the Vercel loader limitation, staging topology, temporary dependency decision, and remaining moderate uuid audit exception.
Define canonical /match, /pit, and /local-data paths in a shared route map, while retaining redirects from the legacy pit and stored URLs.

Update navigation and protected-route handling to use route constants and prevent path casing mismatches.

Replace the inverted submission booleans in the match and pit forms with explicit states. Navigate only after a confirmed upload, preserve locally stored recovery data on failure, disable duplicate submissions, and display clear failure feedback.

Add route and submission regression tests, stabilize the asynchronous authentication draft test, and update the technical, deployment, proposal, and lint-baseline documentation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant