### Dokumentasi Singkat: Setup Firebase Authentication dengan Laravel

Berikut adalah panduan singkat untuk mengonfigurasi Firebase Authentication di Laravel menggunakan Kreait SDK dan Firebase JavaScript SDK.

#### 1. **Alur kerja Firebase**
1. **Login**: Pengguna login melalui Google atau email/password menggunakan Firebase.
2. **Verifikasi Token**: ID Token yang dihasilkan dikirim ke backend, dan Firebase SDK memverifikasinya.
3. **Cek Pengguna di Sistem**: Backend mencari pengguna di sistem atau membuat pengguna baru.
4. **Email Verifikasi**: Jika email belum diverifikasi, login dibatalkan.
5. **Sesi**: Backend mengirimkan cookie sesi Firebase untuk mengidentifikasi pengguna untuk beberapa aplikasi.
6. **Redirect**: Setelah sukses login, frontend mengarahkan pengguna ke halaman tujuan.
7. **Logout**: Pengguna dapat logout, yang akan menghapus sesi Firebase dan cookie.
8. **Verifikasi Sesi**: Middleware memastikan bahwa token Firebase valid pada setiap request yang membutuhkan autentikasi.

#### 2. **Setup Firebase di Firebase Console**

1. **Buka [Firebase Console](https://console.firebase.google.com/)**.
2. Buat proyek baru atau pilih proyek yang sudah ada.
3. **Aktifkan Firebase Authentication**:

   * Pilih **Authentication** > **Sign-in method**.
   * Pilih metode autentikasi yang Anda inginkan (misalnya, **Email/Password** atau **Google**).
4. **Download Credential JSON**:

   * Pergi ke **Project settings** > **Service accounts** > **Generate new private key**.
   * Simpan file `.json` yang berisi kredensial Firebase.

   Note:
   file json sudah disimpan oleh NOC.

#### 3. **Instalasi Kreait Firebase SDK di Laravel**

1. Install Kreait Firebase SDK untuk Laravel:

   ```bash
   composer require kreait/laravel-firebase
   ```

2. **Konfigurasi `.env`**:
    Copy file json yang sudah di download ke directory **storage/app/{disini}**.
   Tambahkan kredensial Firebase yang sudah didownload di file `.env` Laravel:

   ```env
    FIREBASE_CREDENTIALS=app\xxxxxxxxx-xxxxx-firebase-adminsdk-xxxxx-xxxxxxxxxx.json
    FIREBASE_API_KEY=AIzaSyCu4HGxxxxxxxxxxxxxxx-xxxxxxxxx
    FIREBASE_CONTINUE_URL="http://127.0.0.1:8000" // di isi domain atau ip
   ```

3. **Tambahkan konfigurasi di `config/services.php`**:

   ```php
    // Ini configurasi sebelumnya:
    // 'credentials' => env('FIREBASE_CREDENTIALS', env('GOOGLE_APPLICATION_CREDENTIALS')),
    Ubah seperti ini
    'credentials' => [
        'file' => storage_path(env('FIREBASE_CREDENTIALS')),
    ],
   ```

#### 4. **Frontend (Firebase JavaScript SDK)**

1. **Install Firebase JavaScript SDK**:

   ```bash
   npm install firebase
   ```

2. **Firebase Config (di frontend)**:

   Setup Firebase di file `firebase.js` atau langsung di dalam skrip HTML.

   ```javascript
   import firebase from 'firebase/app';
   import 'firebase/auth';

   const firebaseConfig = {
       apiKey: "your-api-key",
       authDomain: "your-auth-domain",
       projectId: "your-project-id",
       storageBucket: "your-storage-bucket",
       messagingSenderId: "your-sender-id",
       appId: "your-app-id",
   };

   if (!firebase.apps.length) {
       firebase.initializeApp(firebaseConfig);
   } else {
       firebase.app();
   }
   ```

3. **Login dengan Google**:

   ```javascript
   const googleLogin = async () => {
       const provider = new firebase.auth.GoogleAuthProvider();
       const result = await firebase.auth().signInWithPopup(provider);
       const idToken = await result.user.getIdToken();

       // Kirim ID Token ke backend
       const response = await fetch('/firebase/login', {
           method: 'POST',
           headers: {
               'Content-Type': 'application/json',
               'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
           },
           body: JSON.stringify({ idToken })
       });

       const data = await response.json();
       if (data.status === 'success') {
           window.location.href = data.redirect;
       }
   };
   ```

#### 5. **Backend (Laravel - FirebaseAuthController)**

1. **Login dengan Firebase ID Token**:

   Controller `FirebaseAuthController.php` menangani verifikasi ID Token dan login pengguna:

   ```php
   use Kreait\Laravel\Firebase\Facades\Firebase;
   use Illuminate\Http\Request;
   use Illuminate\Support\Facades\Auth;

   class FirebaseAuthController extends Controller
   {
       public function loginWithFirebase(Request $request)
       {
           $request->validate([
               'idToken' => 'required|string',
           ]);

           try {
               $auth = Firebase::auth();
               $verifiedIdToken = $auth->verifyIdToken($request->input('idToken'));
               $uid = $verifiedIdToken->claims()->get('sub');

               $firebaseUser = $auth->getUser($uid);
               $user = User::firstOrCreate([
                   'email' => $firebaseUser->email
               ]);
               $user->update(['firebase_uid' => $uid]);

               Auth::login($user);

               return response()->json(['status' => 'success', 'redirect' => '/dashboard']);
           } catch (\Throwable $e) {
               return response()->json(['error' => 'Unauthorized', 'message' => $e->getMessage()], 401);
           }
       }
   }
   ```

2. **Logout**:

   ```php
   public function logout(Request $request)
   {
       Auth::logout();
       return response()->json(['status' => 'logged_out'])->withCookie(cookie('firebase_session', '', -1));
   }
   ```

#### 6 **Middleware (Verify Firebase Session)**

1. **Verifikasi Token di Middleware**:

   Middleware ini memverifikasi token Firebase yang disimpan di cookie.

   ```php
   use Kreait\Laravel\Firebase\Facades\Firebase;

   class VerifyFirebaseSession
   {
       public function handle(Request $request, Closure $next)
       {
           $token = $request->cookie('firebase_session');
           if (!$token) {
               Auth::logout();
               return response()->json(['error' => 'No session'], 401);
           }

           try {
               $auth = Firebase::auth();
               $verifiedToken = $auth->verifyIdToken($token);
               $uid = $verifiedToken->claims()->get('sub');
               $request->attributes->add(['uid' => $uid]);

               return $next($request);
           } catch (\Throwable $e) {
               return response()->json(['error' => 'Invalid or expired session'], 401);
           }
       }
   }
   ```
