vuejs / vuefire

🔥 Firebase bindings for Vue.js
https://vuefire.vuejs.org
MIT License
3.85k stars 332 forks source link

Nuxt VueFire Auth Emulator not Connecting on Reload in Private Browser Window #1312

Closed chrisspiegl closed 1 year ago

chrisspiegl commented 1 year ago

Reproduction

I will try to provide a repo when necessary.

Steps to reproduce the bug

Expected behavior

I expect the login to persist in SSR function calls and all reloads and in normal as well as incognito window browsers.

Actual behavior

Non Private Browser Window

Private Browser Window

Tested in Chrome, Brave, and Brave Beta with the "Private Browsing" window.

I tried figuring this out and debugged to see that the emulator in the browser window can not actually connect on the second call.

I am not sure why this is because it works on the first call and it also works in a non private browser window.

The __SESSION cookie is stored propperly in the browser as well.

However, I did notice that on reload of a currently logged in session the connectAuthEmulator fails with the error auth/emulator-config-failed.

I tried looking this up and it indicates that there has already been a connection made to the auth server. Firebase auth does not seem to allow changing to emulator after a connection to server has been made once.

Additionally, there is an error with the system trying to connect to POST https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=xxxxxxxxx 400 which obviously fails because I have a mock api key set.

Screenshot / Stacktrace Capture 2023-02-22 at 17 54 26

My guess is that somewhere in the vuefire / nuxt-vuefire the useFirebaseAuth in combination with hydration is causing this issue by trying to / automatically verifying the login state of the user.

Additional information

I understand that official emulator support is being worked on. However, I found the connectEmulator functions being talked about in some other issue and that one should just use those. So that's what I tried without a lot of luck. Just found this edge case apparently — which I am not sure about why it's happening or what implications it may have. It's certainly an inconvenience that incognito testing currently doesn't work for me 🙈.

chrisspiegl commented 1 year ago

I did not get to creating a dedicated repo for what I was describing. But I did figure some stuff out and think I have a fix/potential solution for the future.

It seems the issue was mainly coming from the fact that VueFire is initiated before any of my custom nuxt plugins run. This also means that VueFire is trying to initialize the auth state already… But that means we can't update the emulator after that.

I do know that emulator support is on the roadmap. But until then, I think I found a workaround by patching one file in nuxt-vuefire with pnpm patch in my case.

Following it the file I now have basically replaced:

File: nuxt-vuefire/dist/runtime/auth/plugin.client.mjs

import { VueFireAuth } from "vuefire";
import { useFirebaseStorage, useFirestore } from 'vuefire'
import { defineNuxtPlugin, useRuntimeConfig } from "#app";
import { connectAuthEmulator, getAuth } from 'firebase/auth'
import { connectFirestoreEmulator } from 'firebase/firestore'
import { connectStorageEmulator } from 'firebase/storage'

export default defineNuxtPlugin((nuxtApp) => {
  const firebaseApp = nuxtApp.$firebaseApp;
  // CUSTOMIZATION TO SUPPORT AUTH EMULATOR
  // Reason why this has to be inside here:
  // The module `nuxt-vuefire` is loaded before any of other / custom plugins.
  // Thus it tries to confirm the login state of the user right away and sends a request to google.
  // However, we want to work with the emulator, so the emulator has to be initialized before `VueFireAuth` is called.
  // This customization does just that.
  // To enable emulators, make sure to set the build env variable: `NUXT_PUBLIC_USE_FIREBASE_EMULATOR`
  // And potentially adjust the ports / urls / ip addresses of the emulators below.
  const useEmulators = useRuntimeConfig().public?.useFirebaseEmulator
  if (useEmulators) {
    console.log('🔥 Nuxt-Vuefire Should Setup Auth Emulator');
    connectFirestoreEmulator(useFirestore(firebaseApp.name), 'localhost', 9090)
    connectStorageEmulator(useFirebaseStorage(firebaseApp.name), 'localhost', 9199)
    const auth = getAuth(firebaseApp)
    if (!auth) {
      console.log('🔥 NO getAuth insdie the client plugin');
    }
    console.log('🦊 Found the getAuth inside the client plugin');
    try {
      connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings: true })
      console.log('🦊 Successfully initialized the auth emulator');
    } catch (error) {
      console.log('🔥 Error while trying to connect to emulator in nuxt-vuefire/plugin.client.mjs', error);
    }
  }
  // CUSTOMIZATION ENDED
  VueFireAuth(nuxtApp.payload.vuefireUser)(firebaseApp, nuxtApp.vueApp);
});

Yes, this does not work for everybody and it surely is not a full blown implementation of what emulator support should be… but it's a start and it's as much as I have time for at in this moment and I thought this may be valuable for anyone else coming across any issues with the Emulator Initiation with VueFire / Nuxt-VueFire.

posva commented 1 year ago

Closing now that emulators are supported out of the box 🎉