Auth setup (Identity Platform / Firebase)
Purpose
Turn on authentication so that (a) the React UI prompts users to sign in with Google, and (b) the Fastify API rejects calls that don't carry a valid Firebase ID token. This guide walks you through the minimal configuration for local dev and production, the difference between client and server env vars, and the most common wiring mistakes.
Prerequisites
- Required: A Google Cloud project with Identity Platform or Firebase Authentication enabled.
- Required: Ability to set environment variables for both the server (runtime) and the client (build time).
- Required: At least one sign-in method enabled in Firebase Authentication (Google is the default).
- Optional: A list of authorized email addresses if you want to restrict sign-in. Configure this in Firebase or via allowlists in your deployment.
Inputs
- Server env (runtime):
AUTH_REQUIRED=true— flips the API into protected mode.FIREBASE_PROJECT_ID=<gcp-project-id>— must match the project the client tokens come from.GOOGLE_APPLICATION_CREDENTIALS=./secrets/service-account.json— local dev only. In production, use ADC instead (attach a service account to the workload).
- Client env (
client/.env.local, baked at build time):VITE_FIREBASE_API_KEYVITE_FIREBASE_AUTH_DOMAINVITE_FIREBASE_PROJECT_ID
All three VITE_FIREBASE_* values come from Firebase Console → Project Settings → General → "Your apps" → Web app → Config. These values are designed to be public — they identify the project, they don't grant access. The security boundary is the server verifying the ID token.
Outputs
- Protected API routes reject calls without
Authorization: Bearer <idToken>with401 Unauthorized. - Signed-in UI: the React app shows a Google sign-in screen on first load; after sign-in, it attaches the ID token to every API call automatically.
- Token refresh: Firebase's client SDK refreshes tokens before expiry — users don't re-sign-in every hour.
- Operator visibility:
GET /api/auth/configreports the current posture so the client knows whether to prompt.
Constraints
- Production should use ADC, not JSON keys. A service account JSON file in a container image is a credential-exfiltration risk. Attach a service account to the workload (Cloud Run, GKE workload identity, etc.) and let
firebase-adminpick it up automatically. - Client config is build-time. After changing any
VITE_*value you must rebuildclient/distand redeploy — restarting the server has no effect because the browser bundle is already fixed. - Project IDs must match. The server's
FIREBASE_PROJECT_IDand the client'sVITE_FIREBASE_PROJECT_IDmust refer to the same Google Cloud project. Token issuer/audience checks fail otherwise. - Authorized domains matter. Firebase rejects sign-in from domains not on its "authorized domains" list. Add both
localhost(for dev) and your production domain. - Public endpoints stay public.
GET /api/auth/config,/api/openapi.json, and/api/docs/index(for non-gated pages) don't require auth — they're needed to bootstrap the UI.