FirebaseExtended / FirebaseExtended/reactfire

Random permission errors when logging in with multiple tabs open

Ouverte
#574 0 commentaires 2 réactions 0 personnes assignées Voir sur GitHub
v5
Langage dominant
TypeScript
Étoiles
3.6k
Forks
403
Merge moyen
14 h 53 min
PR mergées (30 j)
5

Description

### Version info

**React:** 18.2.0

**Firebase:** 9.15.0

**ReactFire:** 4.2.2

**Other (e.g. Node, browser, operating system) (if applicable):**
Node: 18.4.0

### Test case

When you have multi-tab persistence enabled (`enableMultiTabIndexedDbPersistence`) and you use the default auth persistence mode from `getAuth()` (browser local persistence), and your firebase app is open in multiple tabs, it occasionally fails to load the first requested document with a `code=permission-denied` error:

```
FirebaseError: [code=permission-denied]: Missing or insufficient permissions.
```

Here's a short video demonstrating the problem:

https://user-images.githubusercontent.com/307312/210944853-38bfaf81-dc8e-4627-a29d-c2b31ac4f0a9.mp4

When the tab where the error occurred is reloaded the app loads just fine. The symptoms are very similar to those described in https://github.com/FirebaseExtended/reactfire/issues/485 and https://github.com/FirebaseExtended/reactfire/discussions/228, but the workaround of clearing the observables cache does not prevent this issue from occurring. The problem I'm having here sounds identical to https://github.com/firebase/firebase-js-sdk/issues/1981, but when I try loading the user document with the vanilla firebase SDK I actually don't get any permissions errors. It only happens when using the reactfire hooks.

Unfortunately, due to https://github.com/FirebaseExtended/reactfire/issues/540 it's impossible to catch the permissions error and deal with it, so I've had to resort to a really ugly hack where I inspect the preloaded observables cache, find the observable associated with my user document, and check if `ourError` contains a `permission-denied` error. If it does, I force the window to reload. It's not ideal because the error boundary still flashes for a second, and the error ends up in the console, but it's better than failing to load the app entirely. Here's what the workaround looks like:

```
// In some functional component:
applyReactfireWorkaround(`:users/${authUser.data.uid}`);
const user = useFirestoreDoc(...);

function applyReactfireWorkaround(...keySubstrings: string[]): void {
const reactFirePreloadedObservables = (globalThis as Record)['_reactFirePreloadedObservables'] as
| Map
| undefined;
if (reactFirePreloadedObservables) {
const hasPermissionDeniedError = Array.from(reactFirePreloadedObservables.keys())
.filter((key) => key.startsWith('firestore:'))
.filter((key) => keySubstrings.every((substring) => key.includes(substring)))
.map((key) => reactFirePreloadedObservables.get(key) as SuspenseSubject)
.some((subject) => (subject.ourError as FirebaseError | undefined)?.code === 'permission-denied');
if (hasPermissionDeniedError) {
globalThis.location.reload();
}
}
}
```

### Steps to reproduce

Log in and out of a Firebase app with multi-tab persistence enabled and browser local auth. A document subscription should be made immediately after logging in, e.g. to a document representing the current user.

### Expected behavior

All tabs load successfully.

### Actual behavior

One or more tabs blow up when accessing the first document with `useFirestoreDoc` with the following error:
```
FirebaseError: [code=permission-denied]: Missing or insufficient permissions.
```

Guide de contribution

Ouvrir le guide de contribution

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.