firebase / firebase/firebase-js-sdk

getIdTokenResult() with forceRefresh reruns snapshot listeners that are set to includeMetadataChanges

Open
#8,686 4 comments 0 reactions 1 assignee Claimed by @milaGGL View on GitHub
api: auth api: firestore type: feature request
Dominant language
TypeScript
Stars
5.1k
Forks
1k
Avg merge
2d 21h
Merged PRs (30d)
37

Description

### Operating System

macOS Ventura

### Environment (if applicable)

Google Chrome 131.0.6778.205 (Official Build)

### Firebase SDK Version

10.11.0

### Firebase SDK Product(s)

Firestore, Auth

### Project Tooling

Default React app

### Detailed Problem Description

**Context**

1. The given code requests a new user token - with forceRefresh set to true - every 7 seconds.
2. The code also sets a onSnapshot listener to a test document with `includeMetadataChanges` set to true

**Expected behavior**

1. The `onSnapshot` listener should only run once when the data loads

**Actual behavior**

1. The onSnapshot listener runs each time the new token is generated. The `snapshot.metadata.fromCache` property toggles between true and false each time the listener runs.

**Further observation**: Setting `forceRefresh` to `false` in `getIdTokenResult` fixes the issue

**Conclusion**: It's not obvious why force refreshing the token changes the metadata on the snapshot causing the listener to rerun.

The behavior might be a bug. Hence I have filed this report.
If it's not a bug, I would like to know if there's a way to _skip_ these _unnecessary_ runs of the snapshot listener.

### Steps and code to reproduce issue

```jsx
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { collection, doc, getFirestore, initializeFirestore, onSnapshot, setLogLevel } from 'firebase/firestore';
import React from 'react';
import { createRoot } from 'react-dom/client';

const root = createRoot(
document.getElementById('root')
);

const firebaseConfig = {
...your config...
};

const firebaseApp = initializeApp(firebaseConfig);
initializeFirestore(firebaseApp, {});
const user = getAuth().currentUser; // initialize auth

setTimeout(() => {
onSnapshot(doc(collection(getFirestore(), 'test_collection'), 'test_document'), { includeMetadataChanges: true, }, (snapshot) => {
let data = null;
if (snapshot.exists()) {
data = snapshot.data();
}
console.log('users readonly data', data, snapshot.metadata);
}, undefined);
}, 1000);

setInterval(async () => {
console.log('token got', await getAuth().currentUser.getIdTokenResult(true));
}, 7_000);

function App() {
return

'Hello World'
;
}

root.render();
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.