-
Notifications
You must be signed in to change notification settings - Fork 996
Description
Operating System
iOS
Browser Version
Safari
Firebase SDK Version
10.7.2
Firebase SDK Product:
Auth
Describe your project's tooling
NextJS app with Firebase loading as a dynamic component / separate chunk
Describe the problem
There is a problem with the onAuthStateChanged event callback in Safari on iOS ( or just with authentication in general ). The callback is not always invoked when the app has started, and as a result, the user is stuck while our app is waiting for firebase to finish.
More specifically, the callback can also be invoked unreasonably late, as if firebase is stuck somewhere.
Initially, we could not reproduce this reliably, and have only seen it ourselves a couple of times.
As such, we have added an analytics event in the onAuthStateChanged callback to trigger when and how often firebase loads.
We just found out that the behavior can be triggered by having multiple tabs open to the same site, and after several hours, opening a new tab will get stuck.
Not loading:
| Browser | Sessions Loading | Sessions Not Loading | Ratio |
|---|---|---|---|
| Chrome | 16311503 | 4512 | 0.027 % |
| Firefox | 734236 | 59 | 0.008% |
| Safari | 2053968 | 22709 | 1% |
Delayed loading:
For sessions in which firebase loads we looked at the different percentiles, median and average.
Timings are in ms
| Browser | avg time | 5pct | 25pct | median | 75pct | 95pct |
|---|---|---|---|---|---|---|
| Chrome | 1763 | 2 | 10 | 133 | 497 | 2239 |
| Firefox | 3097 | 1 | 3 | 9 | 134 | 911 |
| Safari | 427408 | 1 | 7 | 77 | 371 | 16964 |
Yes, that average for Safari is correct. For a small subset of users the onAuthStateChanged callback takes an insanely long amount of time to get called.
We have reworked our application a bit to try to not give these users an awful experience.
For users where we suspect that firebase is not loading, but that still stick around long enough, we notice that firebase can eventually load after some time.
Timings are in seconds
| Browser | avg time | 5pct | 25pct | median | 75pct | 95pct |
|---|---|---|---|---|---|---|
| Chrome | 197 | 0 | 5 | 18 | 41 | 163 |
| Firefox | 339 | 0 | 9 | 29 | 76 | 259 |
| Safari | 7578 | 0 | 31 | 235 | 1700 | 38987 |
Chrome and Firefox timings can be explained due to slow devices or networks ( as we're quite a heavy site in terms of downloading assets ), but Safari has other problems.
Steps and code to reproduce issue
We recently ( read, last night ) finally found out that you can get this behavior by having multiple tabs open of site for a couple of hours ( we managed to get it after waiting 2h, we don't know if you can get it sooner ), and then opening a new tab to the site. This tab will be stuck. Refreshing any of the other tabs will also result in them being stuck. Closing some of the tabs will result in a stuck tab to become unstuck.
We haven't looked deeper into how long tabs need to be open, or whether it's a specific tab you need to close.
In case it matters, we've had it happen on a device where we never logged in on firebase, and a device where we had previously logged in. In both cases after a couple of refreshes firebase loaded just fine.
The code boils down to:
const [userLoading, setUserLoading] = React.useState(false);
useEffect(() => {
const cleanup = onAuthStateChanged(firebaseAuth, (newUser) => {
// callback gets never invoked
setUserLoading(false);
};
return cleanup;
}
We have tried other implementations using authStateReady ( which under the hood also use onAuthStateChanged ), where the same problem occurs.
Related issues:
#2167