Skip to content

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

Open
@GaurangTandon

Description

@GaurangTandon

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

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 <div>'Hello World'</div>;
}

root.render(<App />);

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions