javascriptfirebasereact-nativegoogle-cloud-firestorefirebase-security

Why am i getting all documents when I should get none?


In firestore I have a collection called wallets. A random wallet could look like this

name: "Bank of America"
balance: 4000
currency: "eur"
...
user_id: "PhMbbbbbe0XfVSfSwwaaaaaCMj1"

I have set up some dummy security rules that should forbid any action on wallets

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /wallets/{walletId} {
        allow read, write: if false;
    }
  }
}

I have a react native project which uses React Native Firebase to talk to Firebase

import firestore from '@react-native-firebase/firestore';
import { useEffect, useState } from 'react';
import { useSession } from '../authContext';

export type Wallet = {
  name: string;
  balance: number;
  currency: string;
};

export function useWallets() {
  const [wallets, setWallets] = useState<Wallet[]>([]);
  const [loading, setLoading] = useState(true);
  const {session} = useSession();

  useEffect(() => {
    const unsubscribe = firestore()
      .collection('wallets')
      //.where("user_id", "==", session?.user?.uid)
      .onSnapshot(snapshot => {

        if (!snapshot || snapshot.empty) 
          return setLoading(false);

        const wallets: Wallet[] = [];
        snapshot.forEach(doc => {
          wallets.push({
            name: doc.data().name,
            balance: doc.data().balance,
            currency: doc.data().currency,
          });
        });
        setWallets(wallets);
        setLoading(false);

      });

    return () => unsubscribe();
  }, []);

  return { wallets, loading };
}

In the code above I have commented the where clause because i wanted to test the security rules. I want to be sure that a random user isn't able to access some other user's data. Strangely enough, the code above returns all wallets.

I'd expect it to return nothing. As for my understanding, if the rule fails then no result is returned on a read access. And my rule should always fail!

Why am I getting all wallets?


Solution

  • Keep in mind that Firebase caches the data on mobile devices. So if the data was readable before, you might be seeing data from the local cache (before the request is even sent to the server). While the listener will be auto-cancelled once the response from the server comes back (rejecting it), at that stage your app likely is already showing the data from the cache.

    If that sounds like it might be the case, you can wipe the cache by deleting app data (Android) or uninstall/reinstall (iOS).