Step 1: Understanding Security
Time: ~5 minutes | Type: Learning | Concepts: Security vulnerabilities, client vs server validation
What We're Learning
Before we write any security rules, we need to understand why client-side code is not secure and what could go wrong without proper server-side protection.
Before You Code: Ask AI First
💡 Interactive Learning:
Open your AI assistant and ask these questions. Really read the answers!
Why can't I trust security checks in my React code? What is the difference between client-side and server-side validation? If my app checks userId before showing todos, why do I still need security rules? What could an attacker do if I don't have Firestore security rules? Can you show me an example of how someone could bypass my app's UI and access Firestore directly? What are some real-world examples of apps that were hacked due to missing security rules?
What you should learn:
- Client-side code runs in the browser (users control it)
- Users can open DevTools and bypass your app entirely
- Without security rules, anyone can read/write ANY Firestore data
- Attackers can use the browser console to call Firestore API directly
- Real apps have leaked user data due to missing rules
- Server-side rules are the ONLY real security
Understanding the Attack
After asking AI, make sure you understand this scenario:
Your App (Trying to Be Secure)
// Your React component
function TodosPage() {
const { currentUser } = useAuth();
useEffect(() => {
// Only fetch current user's todos
const q = query(
collection(db, 'todos'),
where('userId', '==', currentUser.uid)
);
const todos = await getDocs(q);
setTodos(todos);
}, []);
return <div>{/* Display todos */}</div>;
}You think: "I filtered by userId, so users can only see their own data!"
Attacker's Code (Bypassing Your App)
Attacker opens browser console and types:
// Import Firestore (your config is in the page source)
import { collection, getDocs } from 'firebase/firestore';
import { db } from './firebase'; // Your config is visible
// Get ALL todos from ALL users (no filter!)
const allTodos = await getDocs(collection(db, 'todos'));
allTodos.forEach(doc => {
console.log(doc.data()); // See everyone's data!
});Without security rules: This works. Attacker sees all users' todos.
With security rules: Firestore returns only attacker's todos (or permission denied).
What Could Go Wrong
Scenario 1: Privacy Breach
What happens:
- User A can read User B's personal todos
- Private information leaked (emails, addresses, notes)
- GDPR violation (can be fined up to 4% of revenue)
Real-world: A dating app in 2018 exposed users' private messages due to missing rules. 100,000+ messages leaked.
Scenario 2: Data Manipulation
What happens:
- Attacker deletes competitors' data
- Changes other users' account settings
- Modifies prices in e-commerce app
Real-world: A to-do list app let users delete others' tasks. One user deleted 50,000+ tasks before the vulnerability was fixed.
Scenario 3: Spam and Abuse
What happens:
- Automated script creates millions of fake todos
- Firestore bill skyrockets (you pay per read/write)
- Database becomes unusable
Real-world: A social media app with no write limits had $10,000+ Firestore bill in one day due to spam bots.
Scenario 4: Complete Data Loss
What happens:
- Malicious user writes script to delete all documents
- All users' data gone forever
- No undo, no recovery
Real-world: A classroom app lost all students' work when a student discovered they could delete any document.
Why Client-Side Validation Isn't Enough
Client-side (React) is for UX:
- Instant feedback ("Please enter a title")
- Preventing accidental errors
- Making the app feel responsive
Server-side (Firestore rules) is for security:
- Enforcing who can access what
- Validating data integrity
- Protecting against malicious attacks
- Cannot be bypassed
Analogy:
Think of a bank:
- Client-side: Friendly teller checking your ID
- Server-side: Vault with biometric locks and cameras
The teller improves experience, but the vault is what actually keeps money safe.
Understanding Check
Before moving on, make sure you can answer these:
💡 Ask yourself (or ask AI if unsure):
- Can users bypass React code and access Firestore directly?
- Where do security rules run (browser or server)?
- If my app filters by userId, can attackers still access others' data without rules?
- What's one real-world consequence of missing security rules?
- What's the difference between client-side and server-side validation?
Expected answers:
- Yes, they can open DevTools and write their own code
- Server (Google's servers, not the browser)
- Yes, attackers can remove the filter and query everything
- Privacy breaches, data loss, massive bills, lawsuits, etc.
- Client = UX feedback; Server = actual security enforcement
What You Learned
At this point you should understand:
- ✅ Why client-side code is not secure
- ✅ How attackers can bypass your React app
- ✅ What could go wrong without security rules
- ✅ Why server-side rules are critical
- ✅ That security rules are NOT optional
Next Step
Now that you understand why security rules matter, let's install the Firebase CLI so we can manage rules from your project: