Authentication
The AI Ingredient Scanner uses Firebase Authentication for user management, with Google Sign-In as the primary authentication method and optional guest mode for anonymous usage.
Overview
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β AUTHENTICATION FLOW β β β β ββββββββββ β β β User β β β βββββ¬βββββ β β β β β βΌ β β βββββββββββββββββ β β β Auth State? β β β βββββββββ¬ββββββββ β β β β β βββββββ΄ββββββ¬βββββββββββββββββββ β β βΌ βΌ βΌ β β [Not Signed] [Guest Mode] [Signed In] β β β β β β β βΌ β β β β βββββββββββββ β β β β β Login β β β β β β Screen β β β β β βββββββ¬ββββββ β β β β β β β β β ββββββ΄βββββ β β β β βΌ βΌ β β β β[Google] [Guest] β β β β β β β β β β βΌ β β β β ββββββββββββββ β β β ββ Firebase ββ β β β ββ Auth ββ β β β βββββββ¬βββββββ β β β β β β β β β β βΌ β β β β ββββββββββββββ β β β ββ Firestoreββ β β β ββ Sync ββ β β β βββββββ¬βββββββ β β β β β β β β β β ββββββββ΄βββββ΄βββββββββββββββββββ β β β β β βΌ β β ββββββββββββ β β β Home β β β β Screen β β β ββββββββββββ β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Features
| Feature | Description |
|---|---|
| Google Sign-In | OAuth 2.0 authentication via Firebase |
| Guest Mode | Anonymous usage without account |
| Profile Sync | Firestore persistence across devices |
| Preferences Sync | Allergies, skin type, theme saved to cloud |
| Account Deletion | GDPR-compliant data removal |
Authentication Flow
1. Initial State
When the app launches, it checks for an existing Firebase session:
// AuthContext.tsx
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, async (firebaseUser) => {
setUser(firebaseUser);
if (firebaseUser) {
await syncUserToFirestore(firebaseUser);
}
setLoading(false);
});
return () => unsubscribe();
}, []);2. Login Screen Options
- Continue with Google: Full authentication with profile sync
- Continue as Guest: Anonymous mode (no data persistence)
3. Google Sign-In
Platform-specific implementation for web and native:
const signInWithGoogle = async () => {
if (Platform.OS === 'web') {
// Web: Firebase popup
await signInWithPopup(auth, googleProvider);
} else {
// Native: Expo Auth Session
await promptAsync();
}
};4. Firestore Profile Sync
On successful sign-in, user data syncs to Firestore:
// User document structure
interface FirestoreUser {
uid: string;
email: string | null;
displayName: string | null;
photoURL: string | null;
provider: string;
createdAt: Timestamp;
lastLoginAt: Timestamp;
preferences?: {
allergies: string[];
skinType: SkinType;
expertise: ExpertiseLevel;
theme: ThemeMode;
};
}Preferences Sync
User preferences are managed by PreferencesContext and automatically synced:
Synced Preferences
| Preference | Description | Default |
|---|---|---|
| allergies | Known allergens to flag | [] |
| skinType | Skin type for cosmetic analysis | normal |
| expertise | Explanation complexity | beginner |
| theme | Light or dark mode | light |
Auto-Save with Debouncing
Preferences are saved with a 1-second debounce to prevent excessive writes:
const debouncedSave = useCallback((newPrefs: UserPreferences) => {
if (saveTimeoutRef.current) {
clearTimeout(saveTimeoutRef.current);
}
saveTimeoutRef.current = setTimeout(async () => {
if (user) {
await setDoc(doc(db, 'users', user.uid),
{ preferences: newPrefs },
{ merge: true }
);
}
}, 1000);
}, [user]);Firebase Configuration
Setup
Firebase is configured in src/config/firebase.ts:
const firebaseConfig = {
apiKey: 'your-api-key',
authDomain: 'your-project.firebaseapp.com',
projectId: 'your-project-id',
storageBucket: 'your-project.appspot.com',
messagingSenderId: 'your-sender-id',
appId: 'your-app-id',
measurementId: 'your-measurement-id',
};OAuth Configuration
For Google Sign-In to work:
- Firebase Console: Enable Google provider in Authentication
- Google Cloud Console: Configure OAuth consent screen
- Web Client ID: Add to
AuthContext.tsx
const [request, response, promptAsync] = Google.useAuthRequest({
webClientId: 'your-oauth-client-id.apps.googleusercontent.com',
});User Management
Sign Out
const signOut = async () => {
await firebaseSignOut(auth);
setUserProfile(null);
};Account Deletion (GDPR-Compliant)
Deletion removes all user data from Firestore and Firebase Auth:
const deleteAccount = async () => {
// 1. Delete scan history subcollection
const scansRef = collection(db, 'users', user.uid, 'scans');
const scansSnap = await getDocs(scansRef);
const batch = writeBatch(db);
scansSnap.docs.forEach((scanDoc) => {
batch.delete(scanDoc.ref);
});
// 2. Delete user document
batch.delete(doc(db, 'users', user.uid));
await batch.commit();
// 3. Delete Firebase auth user
await deleteUser(user);
};Firestore Security Rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Users can only access their own data
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
// Scan history subcollection
match /scans/{scanId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
}UI Components
Login Screen
Premium gradient design with:
- App branding and logo
- Feature pills (Scan Labels, AI Analysis, Allergy Alerts)
- Google Sign-In button
- Guest mode option
- Privacy policy link
Profile Section
In Settings, authenticated users see:
- ProfileAvatar: Google photo or colored initial fallback
- Display name and email address
- Sign Out button
- Privacy Policy (in-app modal)
- Collapsible Danger Zone with Delete Account option
Guest users see:
- Guest mode avatar with "G" initial
- Sign In with Google button
- Privacy Policy link
Danger Zone Pattern
Account deletion is protected by a collapsible section to prevent accidental clicks:
const [showDangerZone, setShowDangerZone] = useState(false);
// Toggle with smooth animation
const toggleDangerZone = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setShowDangerZone(!showDangerZone);
};Privacy Policy
The privacy policy is displayed in-app via PrivacyPolicyModal. It covers:
- Data collection and usage
- User rights (access, update, delete)
- Third-party services (Firebase, Google)
- Data retention policies