FirebaseExtended / FirebaseExtended/reactfire

Random permission errors when logging in with multiple tabs open

オープン
#574 コメント 0 件 リアクション 2 件 担当者 0 名 GitHub で見る
v5
主要言語
TypeScript
スター
3.6k
フォーク
403
平均マージ
14時間 53分
マージ済み PR(30日)
5

説明

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

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。