Skip to content

two attempts to connect to auth emulator cause config error #6824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
joaomelo opened this issue Nov 5, 2022 · 9 comments · Fixed by #8750 or #8769
Closed

two attempts to connect to auth emulator cause config error #6824

joaomelo opened this issue Nov 5, 2022 · 9 comments · Fixed by #8750 or #8769
Assignees

Comments

@joaomelo
Copy link

joaomelo commented Nov 5, 2022

[REQUIRED] Environment info

firebase-tools: 11.14.3
Platform: Windows 11

[REQUIRED] Test case

This repo commit.

[REQUIRED] Steps to reproduce

Clone the repo, install the project dependencies with npm i and firebase tools globally, open the windows terminal, and start emulators with firebase emulators:exec --project demo-test "vitest run"

[REQUIRED] Expected behavior

All test cases are able to connect to firebase emulators.

[REQUIRED] Actual behavior

After a test case connect to the emulators, the following ones will throw an error of config failed. See image:

error

But if we changed the connection code from this...

function connectToFirebase(connection) {
  const { useEmulators, ...config } = connection;

  const app = initializeApp(config);
  const auth = getAuth(app);
  const db = getFirestore(app);

  if (useEmulators) {
    connectAuthEmulator(auth, "http://localhost:9099", {
      disableWarnings: true,
    });
    connectFirestoreEmulator(db, "localhost", 8080);
  }

  const firebase = { app, auth, db };
  return firebase;
}

to this...

function connectToFirebase(connection) {
  const { useEmulators, ...config } = connection;

  const app = initializeApp(config);
  const auth = getAuth(app);
  const db = getFirestore(app);

  if (useEmulators && !auth.config.emulator) {
    connectAuthEmulator(auth, "http://localhost:9099", {
      disableWarnings: true,
    });
    connectFirestoreEmulator(db, "localhost", 8080);
  }

  const firebase = { app, auth, db };
  return firebase;
}

all connections go through all right.

pass

I'm claiming this is a bug since there is no documented spec that claims a second connection attempt would fail and that the hack adopted here (!auth.config.emulator) uses an undocumented property that could change anytime. The consequence would be a fragile code that can be easily broken in a future path or minor release.

Thanks.
JM

@joaomelo joaomelo added the bug label Nov 5, 2022
@christhompsongoogle
Copy link

Thanks for the feedback - I'll forward to the team.

@google-oss-bot
Copy link
Contributor

I found a few problems with this issue:

  • I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
  • This issue does not seem to follow the issue template. Make sure you provide all the required information.

@yuchenshi yuchenshi transferred this issue from firebase/firebase-tools Nov 22, 2022
@prameshj
Copy link
Contributor

Thanks for filing this. Is it possible that network calls are being made before a second call to auth emulator? Any network call will result in the init flag set to false -

(auth as AuthInternal)._canInitEmulator = false;
, so future connectAuthEmulator will fail.

we can update the docs to clarify this.

@joaomelo
Copy link
Author

Hi @prameshj,
Thanks for answering.

I don't think a network call is made to the auth service before connecting to the auth emulator. The firebase setup is made at the beginning of the program lifecycle. This is the code:

function connectToFirebase(connection) {
  const { useEmulators, ...config } = connection;

  const app = initializeApp(config);
  const auth = getAuth(app);
  const db = getFirestore(app);

  if (useEmulators) {
    connectAuthEmulator(auth, "http://localhost:9099", {
      disableWarnings: true,
    });
    connectFirestoreEmulator(db, "localhost", 8080);
  }

  const firebase = { app, auth, db };
  return firebase;
}

But there is always the possibility of a bug in my code. Any suggestions on how I could ensure that and get back to you? Like two methods to spy on the execution order.

@prameshj
Copy link
Contributor

Is "connectToFirebase" invoked before each test case? I wonder if this is because each test case makes some network calls (by calling some auth APIs) and hence the issue.

We could consider exposing "emulatorInitialized()" that returns a boolean, to be checked before invoking connectAuthEmulator. WDYT, @yuchenshi @sam-gc

@joaomelo
Copy link
Author

Is "connectToFirebase" invoked before each test case? Yes, it is.

@bdotsamir
Copy link

Hi there! Thought I would chip in my two cents here,

I'm using react, and I made the rookie mistake of calling connectAuthEmulator() outside of a useEffect hook with an empty array of dependencies (thus acting like componentDidMount). Changing this made the error disappear.

Hope this helps!

(p.s: your repo link is broken)

@DellaBitta DellaBitta added bug and removed bug labels Jun 8, 2023
@tzappia
Copy link

tzappia commented Jan 23, 2025

This one is still kicking around but I think it has become more of a problem now that SSR has become more prevalent. I raised a bug in the firebase-tools repo, but they investigated and suggested I raise the bug here.

If you look at the latest AngularFire sample app, even they include a hacky workaround for this issue by checking _canInitEmulator. Is there a reason this needs to be an error? The other emulators don't seem to care if you try to connect to them more than once. The call that is causing this is connectAuthEmulator, not initAuthEmulator, so if you need to init it the first time and not on subsequent calls to connect, I would hope you would just keep those details internal.

@DellaBitta DellaBitta assigned DellaBitta and unassigned yuchenshi Jan 24, 2025
DellaBitta added a commit that referenced this issue Feb 11, 2025
Update the `connectAuthEmulator` function to support its invocation more than once. If the Auth instance is already in use, and `connectAuthEmulator` is invoked with the same configuration, then the invocation will now succeed instead of assert.

This unlocks support for web frameworks which may render the page numerous times with the same instances of auth. Before this PR customers needed to add extra code to guard against calling `connectAuthEmulator` in their SSR logic. Now we do that guarding logic on their behalf which should simplify our customer's apps.

Fixes #6824.
@DellaBitta
Copy link
Contributor

Hi @joaomelo,

This should be fixed in our next release, with changes to Firestore, Auth and RTDB which allow the emulator connect functions to be called repeatedly, even after network operations have begun, so long as the parameters passed to the emulator connect functions is consistent.

Thanks for the bug report!

@firebase firebase locked and limited conversation to collaborators Mar 14, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.