3
votes

I've met with some unexpected behaviour when trying to write my Firebase Storage security rules for an Android app.

To test a simple case, I wrote the following rules:

service firebase.storage {
  match /b/<my-firebase-storage-bucket>/o {
    match /{allPaths=**} {
      allow read: if request.auth.uid == "mystery";
      allow write: if request.auth.uid == "6EP13cYABCciskhKwMTaXYZHS5g1";
    }
  }
}

The effect was that I could only upload a file if I logged into my app with the authorised write uid - "6EP13cYABCciskhKwMTaXYZHS5g1" - but I could still read a file regardless of which uid I was logged in with. So it appeared that only the write rule was actually operative; the read rule was being ignored.

To test further, I rewrote the rules as:

service firebase.storage {
  match /b/<my-firebase-storage-bucket>/o {
    match /{allPaths=**} {
      allow read: if false;
      allow write: if true;
    }
  }
}

This allowed me to both upload and read files when logged into my app: again it seemed that only the write rule was operative.

Can anyone think of a possible explanantion for this?

1
I can't reproduce your results using version 9.4.0. I use putBytes()/getBytes() and Task listeners to detect success and failure. For both sets of rules you posted, I am able to write but get permission failures for read. Can you provide more details about what methods you are using to read/write and how you are sensing read status?Bob Snyder
@qbix - thanks for your help with this. I also have version 9.4.0. For upload, I use StorageReference.putFile(Uri). This returns an UploadTask, to which I have added an onSuccessListener. The listener calls taskSnapshot.getDownloadUrl() when the upload completes. The Url is sent to a "firebaseUri" field in a Realtime Database which the downloader has access to. The change in the "firebaseUri" field triggers a call to populateViewHolder() in a FirebaseRecyclerAdapter, which then loads the image using Glide. The image does actually load, hence the read must have been successful.CKP78

1 Answers

2
votes

You explain in the comment under your question that you use getDownloadUrl() to obtain an URL for the file. You then pass the URL to Glide, which reads the file. The documention for getDownloadUrl() notes that the URL can be used to share the file :

Asynchronously retrieves a long lived download URL with a revokable token. This can be used to share the file with others, but can be revoked by a developer in the Firebase Console if desired.

That suggests to me that the URL is effectively a "shareable link" to the file and security rules defined in Firebase Storage do not apply when the URL is used to access the file. One can think of many cases where it is not possible to apply the rules. For example, when the URL is used in a Glide request, the request does not contain information about the requestor's signed-in UID, it only contains the URL.

If you want to restrict access to a file via the URL, I think you can only do that by restricting access to the URL itself.