Securely saving data in Firestore

别说谁变了你拦得住时间么 提交于 2021-01-27 21:45:42

问题


The Firestore documentation shows examples of how to secure data using Firestore security rules based on the request.auth.uid field. These typically look something like this:

service cloud.firestore {
  match /databases/{database}/documents {
    match /stories/{storyid} {
      // Only the authenticated user who authored the document can read or write
      allow read, write: if request.auth.uid == resource.data.author;
    }
  }
}

That makes perfect sense.

What I don't understand (and doesn't appear to be shown anywhere) is how to set the resource.data.author field securely.

Obviously that can't just be based from the client because then any authenticated user can tamper with the request to set their author to any value.

I thought maybe we are supposed to use CloudFunctions to set that field but at the moment this doesn't work.

The impact of this is pretty clear in the role based access example:

{
  user: "alice",
  content: "I think this is a great story!"
}

Surely there must be a tamper-proof way to set the user field there - otherwise any user can make their comments appear to be from anyone else. This seems bad.

In the Firestore example web app, it seems to set the userId field on the client side and I think it is doing the same in the Android version.

What am I missing?

Edit: as @imjared points out this rule implies that 'alice' in user: "alice" is actually a uid, so I think this is safe.

I knew I was missing something.

match /comments/{comment} {
  allow read: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
                              ['owner', 'writer', 'commenter', 'reader']);
  allow create: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
                                ['owner', 'writer', 'commenter'])
                && request.resource.data.user == request.auth.uid;

回答1:


When the user writes a document to Firebase, they can indeed send any value for the author field they want. But there's no way for them to set request.auth.uid. This last bit in crucial to ensure all (read and write) access is authorized.

The first rules snippet you shared actually has two rules, and it might be easier to separate them out for a moment:

allow read: if request.auth.uid == resource.data.author;
allow write: if request.auth.uid == resource.data.author;

The write rule only allows the operation when the author specific in the request is the same as the request.auth.uid. Since request.auth.uid can't be spoofed, and the value of author will only be accepted if it is the same, the write operation is only allowed if the author field is that of the currently authenticated user.

In fact, that latter rule is more regularly written as:

allow write: if request.auth.uid == request.resource.data.author;

The difference when using request is that it explicitly refers to the document (resource) that is in the write request. The result is the same here whether we use resource or request.resource, but I find it easier to see how security works when thinking of the request here.



来源:https://stackoverflow.com/questions/51237922/securely-saving-data-in-firestore

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!