Anudeep Ananth
Anudeep Ananth

Reputation: 1123

Firebase Cloud Storage rules based on Firestore Data work around

In my firebase app I have

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.

Upvotes: 2

Views: 962

Answers (1)

Renaud Tarnec
Renaud Tarnec

Reputation: 83058

Update dated September 28, 2022

Security Rules in Cloud Storage for Firebase now supports cross-service Rules and let you query your projects’ Firestore data, similar to the get() and exists() functions in Firestore Rules.

See this Firebase blog article and this SO answer from Puf.

Previous answer

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...)

Upvotes: 4

Related Questions