Firebase Authentication
Food Tracker (React + Firebase)
Chapter 11 · Firebase Authentication
Four separate chapters have been quietly waiting for this one. Chapter 6 left read/update/delete permissive "until Chapter 11." Chapter 3 named Firebase Authentication as the real answer to "who's allowed to call this function." Chapter 9 added a data invariant but no ownership check. Chapter 10 said this chapter would finally tighten everything. It's time.
Why This Course Can Afford Auth, Genuinely Cheaply
Adding real sign-in to Food Tracker (FastAPI), Food Tracker (Django), or Food Tracker (React + Express) means building password hashing, session or token management, and a users table or model — real, substantial work each of those courses would be right to treat as a separate topic. This course already has Firebase Authentication sitting right there, provisioned the moment the Firebase project was created back in Chapter 1. Adding real accounts here is a natural extension of infrastructure already paid for and already set up, not a new subsystem to build from scratch — which is exactly why this course's own outline includes it as a real chapter while the other three reasonably treat it as out of scope.
Setting Up Email/Password Sign-In
Enable the Email/Password provider in the Firebase console, then:
Making Item Data Per-User
Every item now needs to record who it belongs to. Chapter 5's own addItem gets one more field:
And every query — Chapter 7's expiry check, Chapter 8's history — adds one more filter: where("userId", "==", auth.currentUser.uid).
The Real Rules Tightening
Chapter 6's own create validation and Chapter 9's own update invariant don't get replaced — they get extended, with an ownership check added alongside what was already there:
Chapter 6's field-shape validation is still exactly there in create. Chapter 9's used-item invariant is still exactly there in update. Both simply gained a request.auth check alongside what they already validated — the rules compose cleanly rather than needing to be rewritten from scratch.
Closing Chapter 3's Own Loop
Callable Cloud Functions automatically receive the caller's request.auth, exactly like Firestore rules do. lookupBarcode and suggestRecipes can now genuinely enforce who's allowed to invoke them, answering Chapter 3's own warning directly:
userId field at all — it never existed as a concept until now. Once the new rules require request.auth.uid == resource.data.userId, those older documents fail that check against every possible user, since there's no value there to match at all — they become permanently inaccessible through the app. This is exactly the same backfill problem Chapter 8 already taught, for nameLower, applied here to ownership instead of search: a field added after real documents already exist needs a one-time script to backfill it, or those documents are effectively lost to any rule that now depends on it.
Where This Course Is Headed
Deployment — Firebase Hosting and deploying the Cloud Functions built across this course — and a capstone tying every chapter together into one complete, working, per-user app.
Hands-On Exercises
Explain why this course can add real Authentication relatively cheaply compared to what Food Tracker (FastAPI), Food Tracker (Django), and Food Tracker (React + Express) would each need to build for the same feature.
📄 View solutionExplain how this chapter's rules extend Chapter 6's create rule and Chapter 9's update rule rather than replacing them. What stayed exactly the same, and what was added?
📄 View solutionExplain why items created before this chapter become permanently inaccessible once the new rules take effect, and connect this directly to Chapter 8's own earlier example of the same underlying problem.
📄 View solutionChapter 11 Quick Reference
- Firebase Authentication — near-free here since the platform already provides it; a bigger lift for every sibling course
userId— added to every item at creation, filtered on in every query- Rules extended, not replaced — Chapter 6's create validation and Chapter 9's update invariant both gain an ownership check alongside what they already checked
- Callable functions get
request.authtoo — closing Chapter 3's own "who's allowed to call this" loop - Pre-existing items lose access — the same backfill problem Chapter 8 already taught for
nameLower, now foruserId - Next chapter: Deployment