1
votes

In my firebase app I have

  • a list of users(all users are registered via Firebase Authentication )
  • a list of followers for each user
  • Each user has added a profile photo, the filename of the photo is unique and is saved in a firestore doc called "photoName" document
  • Only Followers of a user are permitted to read the "photoName" document ( as specified in firestore rules )

I want only the followers to be able to read the profile photo of the user, I have added a rule in cloud storage as follows:

match /profilePhotos/{profilePhotoFile_id} {

  allow read: if request.auth.uid != null

}

The cloud storage rules are set on a file-level so is it accurate for me to assume that only the users who are logged in and are also a follower will be able to read the profile photo of another user? Unless they somehow magically guess the unique names of a photo.

1

1 Answers

3
votes

Is it accurate for me to assume that only the users who are logged in and are also a follower will be able to read the profile photo of another user?

No, because it is possible, with the client SDKs to list all the files in a Cloud Storage bucket, as explained in the doc and your Cloud Storage Security Rules allow any authenticated user to read the profile photos files.

Also note that you cannot read Firestore documents when writing Cloud Storage Security Rules.


One possible approach is to use a Cloud Function to generate a signed URL that you store in the Firestore document AND to forbid read access to the profile photos files. Since Cloud Functions use the Admin SDK they can bypass the security rules.

The following Cloud Function code will generate a signed URL each time a file is added to Cloud Storage and save it in a Firestore document. With this signed URL anyone can read the profile photos file.

It's up to you to adapt it to your case by:

  1. If necessary, only treating the profile photos (check that the file name contains profilePhotos)
  2. Saving the URL in the correct Firestore doc: I guess the file name allows linking back to the user document. Also, you will probably have to change from add() to update().

exports.generateFileURL = functions.storage.object().onFinalize(async object => {

    try {
        const bucket = admin.storage().bucket(object.bucket);
        const file = bucket.file(object.name);

        const signedURLconfig = { action: 'read', expires: '08-12-2025' };

        const signedURLArray = await file.getSignedUrl(signedURLconfig);
        const url = signedURLArray[0];

        await admin.firestore().collection('...').add({ signedURL: url })
        return null;
    } catch (error) {
        console.log(error);
        return null;
    }

});

Two additional considerations:

  • You can use Custom Claims in Cloud Storage Security Rules, but it is not really recommended to use them for your case, see here.
  • You can also use file metadata in Cloud Storage Security Rules, but again it is not adapted to your case (you are not going to add followers Ids in file metadata each time a new follower registers...)