Silent Knight
Silent Knight

Reputation: 89

Firestore rules to restrict users to read/write only their data

I am trying to restrict the users to their own data, but currently the data is being shared. I done some research (SO Question, Firebase Docs), but they have not worked for me. I could've possibly overlooked the solution.

DB rules:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }

    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;

      match /{document=**} {
        allow read, write: if request.auth.uid == userId;
      }
    }
  }
}

DB data:

users: [{
    {userId}: {
        email: "...",
        fullName: "...",
        uId: "..." // same as key
        tasks: [{
            {unique taskId}: {
                id: "...", // same as key
                desc: "...",
                priority: 3,
                completed: false
            }
        }]
    }
}]

Data query (Angular):

this.afStore
    .collection(`users`)
    .doc(`${this.authService.getUserId()}`)
    .collection(`tasks`, ref => {
            return ref
                .where('completed', '==', completed)
                .orderBy(sortField, sortOrder);
        }).snapshotChanges().pipe(
                ...
        );

Is this a rules issue, or data/query issue? I think I am missing something minor with the rules...

Upvotes: 3

Views: 1670

Answers (2)

Denis L
Denis L

Reputation: 3292

I had a similar case, and here is the rule set that works for me:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
      match /{document=**} {
        allow read, write: if request.auth.uid == userId;
      }
    }
  }
}

It is worth noting that I used rules_version = '2', as it changes the behavior of the recursive wildcard

Upvotes: 0

Doug Stevenson
Doug Stevenson

Reputation: 317362

This rule of yours:

match /{document=**} {
  allow read, write: if request.auth != null;
}

Is being unconditionally applied to all documents in your database. When a rule allows access to a document it always grants access to it, no matter what other rules are in play.

What that rule is saying is that all users have read and write access to all documents in your database. If this isn't what you want, remove the rule entirely. Replace it with only rules that allow access to just the documents that should be allowed access to just the users who should be able to do so.

To be perfectly clear - you can't have a rule that allows access to a document be later revoked by another rule. If any rule allows access, then that access will be allowed, no matter what the other rules say.

Upvotes: 2

Related Questions