FirebaseExtended / FirebaseExtended/reactfire

Random permission errors when logging in with multiple tabs open

Aperta
#574 0 commenti 2 reazioni 0 assegnatari Vedi su GitHub
v5
Lingua principale
TypeScript
Stelle
3.6k
Fork
403
Merge medio
14h 53m
PR unite (30g)
5

Descrizione

### 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.
```

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Reproduce the failure using enableMultiTabIndexedDbPersistence, browser-local getAuth() persistence, multiple tabs, and an immediate useFirestoreDoc subscription after login. Start by tracing the ReactFire hooks and Suspense observable path mentioned in the report; done means all tabs load the first document without a permission-denied error.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
firebase, react, typescript
Ambito
authentication, database, frontend
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.