简体   繁体   中英

Security Rules for Cloud Firestore - User access only their own docs

I have a users collection and the following rule obviously works:

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

The following two snippets don't allow access though and I can't figure out why:

// Fails:

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

//Fails:

rules_version = '2';
service cloud.firestore {
  match /{collectionName}/{documentId} {
    allow read, write : if collectionName == "users";
  }
}

I'm looking at this and want something like this:

rules_version = '2';
service cloud.firestore {
  match /users/{userId} {
    allow read: if request.auth.uid == userId;
  }
}

But this also fails. I'm clearly missing the point. How can I allow only the user to access their document?

EDIT

Here's my front end code in my Vuex Store:

async getUserData ({ commit }) {
  const querySnapshot = await getDocs(collection(db, 'users'))
  querySnapshot.forEach((doc) => {
    console.log(`${doc.id} => ${JSON.stringify(doc.data())}`)
  })
},

As I mentioned this will print ( all ) users right now. For example, something like this for each user:

Z9FiUutcAIVnXXXXXXXX => {“machineIds”:{“latest":"a","a":"M6021C67FA","b":"M6021C67FA"},"email":"dave@domain.co.uk","unlock”:”XXX”}

Now, I need to only access the logged in user, as mentioned.

So I played around a little and this 'works' (actually prints all records):

// Works:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{collectionName}/{documentId} {
      allow read, write : if collectionName == "users";
    }
  }
}

But these don't and give Uncaught (in promise) FirebaseError: Missing or insufficient permissions. :

// Fails:

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

// Fails:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{email} {
      allow read: if request.auth.token.email == email;
    }
  }
}

I tried the second and expected it to work because my data structure is like so and doesn't have a userId .

Here is my data structure:

结构体

I also played around a little with the Rules Playground to no avail.

I feel incredibly embarrassed to ask about this as I know I'm doing something wrong and the solution is super simple. Any help would be fantastic.

It's important to keep in mind that security rules are not filters . Security rules do not change the result of a query -- they simply allow or deny a query based on the criteria you define. The client code is requesting all of the documents under users , and the result of that query will either be everything or an error saying that they are not allowed to have everything.

If a user should only be able to get their own documents, you will need to add a filter into the query that requests only those documents, and check that the filter is correct in the rules. Typically people use the Firebase Auth UID as the value to store in a document or its ID to determine if it should be usable that by that user.

Also you should know that match expressions only look at the path of the document with collection and document names. They don't match fields of documents like you're trying to do with email. If you want a user to only be able to get documents where their Firebase Auth email address is a certain value, then your rule should look like this:

  match /databases/{database}/documents {
    match /users/{id} {
      allow read: if request.auth.email == resource.data.email;
    }
  }

You will want to take some time to learn about what resource does in your queries. The documentation for "Secure and query documents based on a field" will help.

With that rule, now your client app's query needs a filter on the email with the exact value of their auth email string (which is only guaranteed to be present when using email/password auth).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM