Skip to content
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

🐛 [firebase_auth] WEB - using multiple emulators messes with firebaseEmulatorOrigin #10763

Closed
just7mile opened this issue Apr 11, 2023 · 13 comments · Fixed by #10766
Closed
Assignees
Labels
platform: web Issues / PRs which are specifically for web. plugin: auth type: bug Something isn't working

Comments

@just7mile
Copy link

Bug report

Describe the bug
This issue is related to #10200 which was fixed by #10565. But I could not comment there, so I created a new issue.

The problem is with the fix, because it uses session storage to store auth emulator origin in the firebaseEmulatorOrigin, and uses it to check authentication state after refreshing the page. But when there are multiple emulators used at the same time, which ever is set up latest replaces the value for the firebaseEmulatorOrigin, and after refreshing the page the authentication token is sent to a different origin which causes invalid token error, which brings to the same situation as in #10200.

I think it can be solved by checking and storing in the firebaseEmulatorOrigin only origin of the default project. Or store origin of each project separately.

Steps to reproduce

Steps to reproduce the behavior:

  1. Setup default project.
  2. Sign in into the default project.
  3. Later (maybe after user taking some action) setup another project.
  4. Look into the session storage for the firebaseEmulatorOrigin. Its value is changed to the second project's origin.
  5. Refresh the page and get the error.

Expected behavior

The firebaseEmulatorOrigin should always have origin of the default project.

@Lyokone have a look into this, please.

@just7mile just7mile added Needs Attention This issue needs maintainer attention. type: bug Something isn't working labels Apr 11, 2023
@Lyokone Lyokone self-assigned this Apr 11, 2023
@Lyokone
Copy link
Contributor

Lyokone commented Apr 11, 2023

Hey, thanks for your feedback. Even with hot reload, I'm not getting the auth/emulator-config-failed error. Do you have something to reproduce it?

@just7mile
Copy link
Author

just7mile commented Apr 11, 2023

@Lyokone Thank you for such a quick response! I copy pasted you changes in my local packages, and it is working just fine. But, when hot reloading, it gives auth/emulator-config-failed error fired from the line 102. Maybe it should be wrapped with a try-catch and this error specifically handled same as in the useAuthEmulator function?

       if (emulatorOrigin != null) {
          authDelegate.useAuthEmulator(emulatorOrigin); // --> gives error
          // ignore: avoid_print
          print(
            'Using previously configured Auth emulator at $emulatorOrigin for ${firebaseApp.name} \nTo switch back to production, restart your app with the emulator turned off.',
          );
        }

Another suggestion, isn't it better to call delegate.useAuthEmulator(origin); on the line 468 after saving the origin in the session storage, because if calling delegate.useAuthEmulator(origin); throws error, it does not set the origin into the session storage. This also, gives error when the app first started:

image

Trying to login gives:
image

After a refresh errors are gone and everything works fine.

@Lyokone
Copy link
Contributor

Lyokone commented Apr 11, 2023

@just7mile The reason why we first run the delegate.useAuthEmulator(origin); then save the origin into the sessionStorage, is to avoid saving a wrong origin if the call fails.

Have you totally restarted the app before running the modified code? I don't see any of this errors during my testing.

@just7mile
Copy link
Author

just7mile commented Apr 11, 2023

@just7mile The reason why we first run the delegate.useAuthEmulator(origin); then save the origin into the sessionStorage, is to avoid saving a wrong origin if the call fails.

Have you totally restarted the app before running the modified code? I don't see any of this errors during my testing.

@Lyokone here are steps to reproduce.

For the console error:

  1. Start the app with a specific port --web-port 8080. No error, everything fine.
  2. Sign in.
  3. Stop the app without logging out.
  4. Start the app again with the same port --web-port 8080 and have a look at console.

For the hot restart error:

  1. Start the app.
  2. Sign in.
  3. Refresh the page.
  4. Hot restart (r). The exception should be thrown.

@Lyokone
Copy link
Contributor

Lyokone commented Apr 11, 2023

In both scenarios that you described, I don't get any issues. When you say "stop the app", it means closing the Chrome debug window and launching the app again using flutter run? It should wipe all previous state so you should not be sign in from the previous session.

@darshankawar darshankawar added triage Issue is currently being triaged. plugin: auth platform: web Issues / PRs which are specifically for web. and removed Needs Attention This issue needs maintainer attention. triage Issue is currently being triaged. labels Apr 11, 2023
@just7mile
Copy link
Author

just7mile commented Apr 11, 2023

Yes, here what I did for the hot restart error. I started the app by:

flutter run -d chrome --flavor development --target lib/main_development.dart

Logs:

Launching lib/main_development.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...             22.6s
This app is linked to the debug service: ws://127.0.0.1:52181/cmuZ2kc3bV4=/ws
Debug service listening on ws://127.0.0.1:52181/cmuZ2kc3bV4=/ws

💪 Running with sound null safety 💪

🔥  To hot restart changes while running, press "r" or "R".
For a more detailed help message, press "h". To quit, press "q".

An Observatory debugger and profiler on Chrome is available at: http://127.0.0.1:52181/cmuZ2kc3bV4=
The Flutter DevTools debugger and profiler on Chrome is available at: http://127.0.0.1:9100?uri=http://127.0.0.1:52181/cmuZ2kc3bV4=

Signed in in the app.
Logs:

WARNING: You are using the Auth Emulator, which is intended for local testing only.  Do not use with production credentials.
Using previously configured Auth emulator at http://localhost:10300 for [DEFAULT]
To switch back to production, restart your app with the emulator turned off.

Pressed r.
Logs:

Performing hot restart...                                           96ms
Restarted application in 97ms.
══╡ EXCEPTION CAUGHT BY BOOTSTRAP ╞═════════════════════════════════════════════════════════════════
The following _Exception was thrown [ZONED]:
Exception: FirebaseError: Firebase: Auth instance has already been used to make a network call. Auth
can no longer be configured to use the emulator. Try calling "connectAuthEmulator()" sooner.
(auth/emulator-config-failed).

When the exception was thrown, this was the stack:
https://www.gstatic.com/firebasejs/9.18.0/firebase-auth.js 1:26682                B
https://www.gstatic.com/firebasejs/9.18.0/firebase-auth.js 1:26754                K
https://www.gstatic.com/firebasejs/9.18.0/firebase-auth.js 1:54348                $e
packages/firebase_auth_web/src/interop/auth.dart 711:20                           useAuthEmulator
packages/firebase_auth_web/firebase_auth_web.dart 102:23                          <fn>
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54                runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5                _async
packages/firebase_auth_web/firebase_auth_web.dart 94:46                           <fn>
packages/firebase_core_web/src/firebase_core_web.dart 311:41                      <fn>
dart-sdk/lib/internal/iterable.dart 393:20                                        moveNext
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 781:20  next
dart-sdk/lib/async/future.dart 520:16                                             wait
packages/firebase_core_web/src/firebase_core_web.dart 303:18                      initializeApp
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50                <fn>
dart-sdk/lib/async/zone.dart 1406:47                                              _rootRunUnary
dart-sdk/lib/async/zone.dart 1307:19                                              runUnary
dart-sdk/lib/async/future_impl.dart 147:18                                        handleValue
dart-sdk/lib/async/future_impl.dart 767:44                                        handleValueCallback
dart-sdk/lib/async/future_impl.dart 796:13                                        _propagateToListeners
dart-sdk/lib/async/future_impl.dart 567:5                                         [_completeWithValue]
dart-sdk/lib/async/future_impl.dart 640:7                                         <fn>
dart-sdk/lib/async/zone.dart 1398:13                                              _rootRun
dart-sdk/lib/async/zone.dart 1300:19                                              run
dart-sdk/lib/async/zone.dart 1208:7                                               runGuarded
dart-sdk/lib/async/zone.dart 1248:23                                              callback
dart-sdk/lib/async/schedule_microtask.dart 40:11                                  _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                                   _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15               <fn>

I also cleaned the Chrome cache, restarted the computer, before trying.

I use email link authentication, thus to sign in I paste the link which reloads the page. Could it be the issue?

@just7mile
Copy link
Author

@Lyokone can you, please, after signing in, refresh the page then try to hot restart?

@just7mile
Copy link
Author

just7mile commented Apr 11, 2023

Also the console error occurs if the same port used between app runs --web-port 8080.

image

Updated the steps to reproduce in the comment above.

@Lyokone
Copy link
Contributor

Lyokone commented Apr 11, 2023

@just7mile Thanks for your feedback I managed to get the error. Can you try the updated version I've pushed to the PR?

@just7mile
Copy link
Author

@just7mile Thanks for your feedback I managed to get the error. Can you try the updated version I've pushed to the PR?

Thank you! The hot restart error is gone and it is working now.

But, I'm still getting the console error when using the same port. Were you able to get this error when using same port between runs?

@Lyokone
Copy link
Contributor

Lyokone commented Apr 11, 2023

I've tried a couple of things to get past the error on the same port, but unfortunately, the Firebase JS SDK takes over from the storage that is not cleared between sessions. Clearing site data and reloading the website make the errors disappear. Currently, I would advise keeping rotating port when using the emulator locally.

@just7mile
Copy link
Author

Actually this is not a big problem, the error can be resolved by manually refreshing the page once after starting the app.

@Lyokone
Copy link
Contributor

Lyokone commented Apr 11, 2023

Even if the error is not showing, you might not be connected to the emulator if the bug occurred before during this Chrome session (you have to see this message):
Screenshot 2023-04-11 at 15 42 11

Playing with a bit, you can add this to your index.html body.

It will clear this correct IndexedDB database when reloading the page, but not when hot reloading with Flutter.

    <script>
      if (window.location.hostname == 'localhost') {
        window.indexedDB.deleteDatabase('firebaseLocalStorageDb');
      }
    </script>

@firebase firebase locked and limited conversation to collaborators May 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
platform: web Issues / PRs which are specifically for web. plugin: auth type: bug Something isn't working
Projects
None yet
3 participants