Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase - Limit file access to specific users

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

  • User logs in using Firebase Authentication
  • User uploads a file to Firebase Storage
  • User enters an email address of a different user. This user account may already exist. If not, the recipient gets an email prompting them to sign up.
  • The uploaded file should now be available only to the user who uploaded it (read/write) and to the other user with the above email address (read only).

This is what I've been trying so far:

  • After using FirebaseAuth to sign up, I store the user's email address and uid in the Real-Time Database.
  • After the user uploads a file and enters the recipient's email address, I check the Real-Time Database for that address. If it exists, I retrieve the recipient's uid and store it in the file's metadata.
  • In my Firebase Storage security rules, I check if the auth.uid matches the uid stored in the file metadata.

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

  • I could create a new account after the user enters the recipient's email address. If I do that though, I have to specify a password. I could specify a random password and use the password reset email, but that isn't a good user experience, also because you can't fully customize the reset email.

  • If I don't create the new account right away, how can I make sure that only the user with this email address can access the file? Storing the email address in the file's metadata doesn't work since it could change later.

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?

like image 863
avf Avatar asked Sep 02 '25 04:09

avf


1 Answers

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.

like image 76
Jay Avatar answered Sep 05 '25 01:09

Jay