
# [Auth] Implement Firebase Authentication via krowSDK Facade

Labels: feature, infra, platform:web, platform:backend, priority:high, sred-eligible
Milestone: Foundation & Dev Environment Setup

### 🎯 Objective

Replace the Base44 authentication client with a new internal SDK module, `krowSDK.auth`, backed by Firebase Authentication. This foundational task will unblock all future backend development and align the web application with the new GCP-based architecture.

### 🔬 SR&ED Justification

- **Technological Uncertainty:** What is the optimal way to create a seamless abstraction layer (`krowSDK`) that perfectly mimics the existing `base44` SDK's interface to minimize frontend refactoring, while integrating a completely different authentication provider (Firebase Auth)? A key uncertainty is how this facade will handle the significant differences in user session management and data retrieval (e.g., custom user fields like `user_role` which are not native to the Firebase Auth user object) between the two systems.
- **Systematic Investigation:** We will conduct experimental development to build a `krowSDK.auth` module. This involves systematically mapping each `base44.auth` method (`me`, `logout`, `isAuthenticated`) to its Firebase Auth equivalent. We will investigate and prototype a solution for fetching supplementary user data (like `user_role`) from our Firestore database and merging it with the core Firebase Auth user object. This will establish a clean, reusable, and scalable architectural pattern for all future SDK modules.

### Details

This task is the most critical prerequisite for migrating our backend. As defined in the `03-backend-api-specification.md`, every request to our new Data Connect and Cloud Functions API will require a `Bearer <Firebase-Auth-Token>`. Without this, no backend work can proceed.

#### The Strategy: A Facade SDK (`krowSDK`)

Instead of replacing `base44` calls with Firebase calls directly throughout the codebase, we will create an abstraction layer, or "Facade". This approach has three major benefits:

1.  **Simplified Migration:** The new `krowSDK.auth` will expose the *exact same methods* as the old `base44.auth`. This means we can swap out the authentication logic with minimal changes to the UI components, drastically reducing the scope of refactoring.
2.  **High Maintainability:** All authentication logic will be centralized in one place. If we ever need to change providers again, we only modify the SDK, not the entire application.
3.  **Clear Separation of Concerns:** The UI components remain agnostic about the authentication provider. They just need to call `krowSDK.auth.me()`, not worry about the underlying implementation details.

#### Implementation Plan

The developer should create two new files:

**1. Firebase Configuration (`frontend-web/src/firebase/config.js`)**

This file will initialize the Firebase app and export the necessary services. It's crucial to use environment variables for the configuration keys to keep them secure and environment-specific.

```javascript
// frontend-web/src/firebase/config.js

import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";

// Your web app's Firebase configuration
// IMPORTANT: Use environment variables for these values
const firebaseConfig = {
  apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
  authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
  projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
  storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
  appId: import.meta.env.VITE_FIREBASE_APP_ID
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

// Export Firebase services
export const auth = getAuth(app);
export const db = getFirestore(app);

export default app;
```

**2. Krow SDK (`frontend-web/src/lib/krowSDK.js`)**

This is the core of the task. This file will implement the facade, importing the Firebase `auth` service and recreating the `base44.auth` interface.

```javascript
// frontend-web/src/lib/krowSDK.js

import { auth, db } from '../firebase/config';
import {
  onAuthStateChanged,
  signOut,
  updateProfile,
  // Import other necessary auth functions like signInWithEmailAndPassword, createUserWithEmailAndPassword, etc.
} from "firebase/auth";
import { doc, getDoc } from "firebase/firestore";

/**
 * A promise-based wrapper for onAuthStateChanged to check the current auth state.
 * @returns {Promise<boolean>} - A promise that resolves to true if authenticated, false otherwise.
 */
const isAuthenticated = () => {
  return new Promise((resolve) => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      unsubscribe();
      resolve(!!user);
    });
  });
};

/**
 * Fetches the current authenticated user's profile.
 * This function mimics `base44.auth.me()` by combining the Firebase Auth user
 * with custom data from our Firestore database (e.g., user_role).
 * @returns {Promise<object|null>} - A promise that resolves with the user object or null.
 */
const me = () => {
  return new Promise((resolve, reject) => {
    const unsubscribe = onAuthStateChanged(auth, async (user) => {
      unsubscribe();
      if (user) {
        try {
          // 1. Get the core user from Firebase Auth
          const { uid, email, displayName } = user;
          const baseProfile = {
            id: uid,
            email: email,
            full_name: displayName,
          };

          // 2. Get custom fields from Firestore
          // We assume a 'users' collection where the document ID is the user's UID.
          const userDocRef = doc(db, "users", uid);
          const userDoc = await getDoc(userDocRef);

          if (userDoc.exists()) {
            const customData = userDoc.data();
            // 3. Merge the two data sources
            resolve({
              ...baseProfile,
              user_role: customData.user_role, // Example custom field
              // ... other custom fields from Firestore
            });
          } else {
            // User exists in Auth but not in Firestore. This can happen during sign-up.
            // Resolve with base profile; the app should handle creating the Firestore doc.
            resolve(baseProfile);
          }
        } catch (error) {
          console.error("Error fetching user profile from Firestore:", error);
          reject(error);
        }
      } else {
        // No user is signed in.
        resolve(null);
      }
    });
  });
};

/**
 * Updates the current user's profile.
 * This mimics `base44.auth.updateMe()`.
 * @param {object} profileData - Data to update, e.g., { full_name: "New Name" }.
 */
const updateMe = async (profileData) => {
  if (auth.currentUser) {
    // Firebase Auth's updateProfile only supports displayName and photoURL.
    if (profileData.full_name) {
      await updateProfile(auth.currentUser, {
        displayName: profileData.full_name,
      });
    }
    // For other custom fields, you would need to update the user's document in Firestore.
    // const userDocRef = doc(db, "users", auth.currentUser.uid);
    // await updateDoc(userDocRef, { custom_field: profileData.custom_field });
  } else {
    throw new Error("No authenticated user to update.");
  }
};

/**
 * Logs the user out and redirects them.
 * @param {string} [redirectUrl='/'] - The URL to redirect to after logout.
 */
const logout = (redirectUrl = '/') => {
  signOut(auth).then(() => {
    // Redirect after sign-out.
    window.location.href = redirectUrl;
  }).catch((error) => {
    console.error("Logout failed:", error);
  });
};

// The krowSDK object that mimics the Base44 SDK structure
export const krowSDK = {
  auth: {
    isAuthenticated,
    me,
    updateMe,
    logout,
    // Note: redirectToLogin is not implemented as it's a concern of the routing library (e.g., React Router),
    // which should protect routes and redirect based on the authentication state.
  },
  // Future modules will be added here, e.g., krowSDK.entities.Event
};
```

### ✅ Acceptance Criteria

- [ ] A `frontend-web/src/firebase/config.js` file is created, correctly initializing the Firebase app using environment variables.
- [ ] A `frontend-web/src/lib/krowSDK.js` file is created and implements the `krowSDK.auth` facade.
- [ ] The `krowSDK.auth` module exports `isAuthenticated`, `me`, `updateMe`, and `logout` functions with interfaces identical to their `base44.auth` counterparts.
- [ ] Key parts of the application (e.g., login pages, user profile components, auth checks) are refactored to import and use `krowSDK.auth` instead of `base44.auth`.
- [ ] A new user can sign up using a Firebase-powered form.
- [ ] An existing user can log in using a Firebase-powered form.
- [ ] The application UI correctly updates to reflect the user's authenticated state (e.g., showing user name, hiding login button).
- [ ] After logging in, the user's Firebase Auth ID Token can be retrieved and is ready to be sent in an `Authorization: Bearer` header for API calls.
