Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

233
Views
Adding Firestore rule "&& request.auth.uid == userId;" results in"Error in snapshot listener: FirebaseError: Missing or insufficient permissions."

I'm building an app and setting the firestore rules to only allow users CRUD access to their data in a simple, single-layer DB.

Firestore Rules

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /todos/{userId} {
      allow create, read, update, delete: if request.auth != null && request.auth.uid == userId;
    }
  }
}

If I only use the if statement if request.auth != null the user is able to see all data in the DB.

when I add&& request.auth.uid == userId I get the console error, "react_devtools_backend.js:4061 Uncaught Error in snapshot listener: FirebaseError: Missing or insufficient permissions." The user can't see any data, including their own.

I've read the docs but am missing something-- I think either in my query, snapshot, or both?

Here's my code:

Init firebase (firebase.js)

// init Firebase
export const app = initializeApp(firebaseConfig);

//init services
export const db = getFirestore(app);
export const auth = getAuth();

and then my query and snapshot (app.js)

import React, { useState, useEffect } from "react";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import InputGroup from "react-bootstrap/InputGroup";
import "./App.css";
import Todo from "./components/Todo";
import { db } from "./firebase";
import {
  collection,
  query,
  orderBy,
  onSnapshot,
  addDoc,
  serverTimestamp,
} from "firebase/firestore";

//collection ref, order by functionality

const q = query(
  collection(db, "todos"),
  orderBy("timestamp", "desc")
);

//firebase functionality
function App({ user }) {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState("");
  useEffect(() => {
    onSnapshot(q, (snapshot) => {
      setTodos(
        snapshot.docs.map((doc) => ({
          id: doc.id,
          item: doc.data(),
        }))
      );
    });
  }, [input]);
  const addTodo = (e) => {
    e.preventDefault();
    addDoc(collection(db, "todos"), {
      todo: input,
      timestamp: serverTimestamp(),
      userId: user.uid,
    });
    setInput("");
  };

I'd appreciate any guidance/tips. I've been working through this for a couple days now. Thanks!

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

With Frank's guidance I was able to find a solution. Thanks Frank!

These are my updated rules

rules_version = '2';
service cloud.firestore {
   match /{todos=**} {
      allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
      allow create: if request.auth !=null;
      }
  }

My updated query and snapshot

import React, { useState, useEffect } from "react";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import InputGroup from "react-bootstrap/InputGroup";
import "./App.css";
import Todo from "./components/Todo";

import {
  collection,
  query,
  orderBy,
  onSnapshot,
  addDoc,
  serverTimestamp,
  where,
} from "firebase/firestore";
import { db } from "./firebase";

//firebase functionality
function App({ user }) {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState("");
  const [lastChange, setLastChange] = useState("");

  //executing the query
  useEffect(() => {
    //console.log(user);
    if (user == null) return;

    var q = query(
      collection(db, "todos"),
      orderBy("timestamp", "desc"),
      where("userId", "==", user.uid)
    );

    onSnapshot(q, (snapshot) => {
      setTodos(
        snapshot.docs.map((doc) => ({
          id: doc.id,
          item: doc.data(),
        }))
      );
    });
  }, [lastChange, user]);

  //add a new task
  const addTodo = (e) => {
    e.preventDefault();
    addDoc(collection(db, "todos"), {
      todo: input,
      timestamp: serverTimestamp(),
      userId: user.uid,
    });
    setInput("");
    setLastChange(serverTimestamp());
  };
about 4 years ago · Juan Pablo Isaza Report

0

Your security rules allow the user to read exactly one document, at the path /todos/$uid. Your code however tries to read the entire todos collection, which the rules don't allow. That explains the error you get.

Keep in mind that rules are not filters, but instead merely enforce that you're not trying to read (or write) more data than is allowed. If you want to read the current user's document, you should wait until the current user is loaded (using an auth state listener) and then only load that user's document.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!