avf
avf

Reputation: 850

Firebase - Limit file access to specific users

I'm trying to achieve the following behavior using Firebase:

This is what I've been trying so far:

This should work well, but what do I do if the user account does not yet exist?

I have a feeling I'm thinking way too complicated here. Is there an easier way to achieve this, or am I overlooking something?

EDIT: I've investigated a bit more and I think one way to do this would be by using a custom auth token, which is suggested by the Firebase Storage guide here. That would require me to setup my own auth server though, which kind of defeats the purpose of using Firebase Authentication in the first place. Is there an easier way to achieve this?

Upvotes: 4

Views: 2616

Answers (2)

Woody Jean-louis
Woody Jean-louis

Reputation: 535

Hey to accomplish what you want to do you'll have to add the uid of the users allowed to read the file in the file's metadata then check if the token's uid is contained in the metadata.

Something like this:

match /internal/{imageId} {
  allow read: if resource.metadata[request.auth.uid] != null;
}

resource.metadata is a map so to keep things organized you can have all of the uid with permission to read under a canRead parameter so it'll look like this:

match /internal/{imageId} {
   allow read: if resource.metadata.canRead[request.auth.uid] != null;
}

To manage the metadata read through firebase's documentation under "Use File Metadata" https://firebase.google.com/docs/storage/

Read more about security here: https://firebase.google.com/docs/storage/security/user-security, https://firebase.google.com/docs/reference/security/storage

Also I am not sure if filling your metadata with uids is a good practice. I'm not sure if there is a limit to how much data you save there. Hope this helps!

Upvotes: 1

Jay
Jay

Reputation: 35648

This should be fairly straightforward:

files
  file_id_0
    file_name: My File
    read_write: uid_0
    read_only:
      uid_1: true
      uid_2: true

and of course you have users

users
  uid_0
    name: Larry
    email: [email protected]
  uid_1
    name: Curly
    email: [email protected]
  uid_2
    name: Moe
    email: [email protected]

and some spiffy conceptual rules

rules
  .read: false
  .writ: false
  files
    $file_id
      //give the person that uploaded the file read access to this node as well as
      //  any user id that exists in the read_only node
      .read: root.child('files').child($file_id).child('read_write').val = auth.uid ||
            root.child('files').child($file_id).child("read_only').child(auth.uid) = true
     //write access only to the user that created it
     .write: root.child('files').child($file_id).child('read_write').val = auth.uid

That's pretty close.

So when uid_0 uploads a file, My File, it is stored in file_id_0. That user then 'invites' another user via their email (assume they exist) to that file. In this case uid_0 invites uid_1 and uid_2 and those user ids are written to the file_id_0 node. Those would be obtained by querying the /users node for those two users.

The sticking point is inviting another user that doesn't already exist.

I think they play there is to have an email watch list node.

watch_list
   uid_0
     [email protected]:  file_id_0

each user observers the users node and if a newly added user email exists in their watch list (uid_0 is watching for [email protected]). Then add them to the file_id_0 /read_only node and remove it from the watch list.

Looking at what I just wrote, it's a bit unelegant so there's probably a better way.

Upvotes: 2

Related Questions