-
Notifications
You must be signed in to change notification settings - Fork 996
Description
Describe your environment
- Operating System version:
- iphone X / ios 12.3.1
- iphone 6S / ios 12.3.1/12.4.1
- Browser version: mobile safari
- Firebase SDK version: 6.6.0, 6.4.0
- Firebase Product: auth
Describe the problem
When there are multiple tabs open on mobile Safari for the same app, sometimes a tab's auth will not initialize:
onAuthStateChange()never calls its callback- all methods, including
auth.signOut(), return promises that don't work and never resolve
Steps to reproduce:
Within mobile safari, load the app, log in, and then load the same app in a number more tabs. To test, you can use this url with email test@example.com and password test1234:
https://iphone-tabs-auth-bug.firebaseapp.com/
You can see it in action with this gif.
I've tested this on multiple phones, and multiple versions of iOS. There are times when everything seems to work across 10 or 20 tabs (and the 21st one breaks). But critically, in a larger production app, I've found that even the second tab often fails. This is really bad for the registration flow, where the user registers within mobile safari, clicks on the link in the verification email (which opens in a second tab), and then the app hangs because all auth functions return promises that never resolve.
Relevant Code:
Here's the code for the above test repo, along with details discussion and a gif/images.
https://github.com/jamesknelson/iphone-tabs-auth-bug
What's happening internally
I've done some investigation, and the issue seems to be IndexedDB database is opening properly, but then the first set request is getting stuck in a pending state and never calling any of its callbacks -- even after minutes.
To reproduce this:
- use Safari's dev tools to load the page from an iphone enough times to appear just like the above screenshot
- log the request received by the
onIDBRequest_()function in packages/auth/src/storage/indexeddb.js - you'll see that the request in the console stays pending indefinitely
As to why this is happening -- I have no idea. Removing the transaction by modifying the set() method from this:
var objectStore = self.getDataObjectStore_(
self.getTransaction_(dbTemp, true));to this:
var objectStore = db.createObjectStore(this.objectStoreName_);prevents the hang, but also generally results in each new tab requiring the user to login (although it does seem to enable persistence while reloading the same tab).
There are no workarounds!
Also worth mentioning is that there do not seem to be any work arounds. Once a tab gets in this state, it's stuck there. Reloading does nothing. There's also no way to programmatically work around it. I've tried:
- unsubscribing from
onAuthStateChange()and calling it again - calling auth.delete() and recreating it
- programatically deleting the firebase indexeddb
- combinations of the above
I'd really appreciate any help here. This is causing users of our app to run into never-ending loading spinners when they click verification emails after registering, which really isn't a good look -- and the best I can do is ask customers to close all their tabs and click the link again.
