19
votes

I'm using firebase storage to store and load images for users on my android app. All users must be authenticated before using it. Occasionally, some user profile images are not showing and throwing "403 Forbidden" error. Those images were displaying before, I'm not sure why they stop working. i'm using the following rules on my firebase storage:

 service firebase.storage {
   match /b/<storage_address>.appspot.com/o {
    match /{allPaths=**} {
     allow read: if request.auth != null;
     allow write: if request.auth != null;
    }
  }
}

if i change the read rule to allow read; all the images are working properly. This is my display method:

Picasso.Builder builder = new Picasso.Builder(this);
                builder.listener(new Picasso.Listener()
                {
                    @Override
                    public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception)
                    {
                        exception.printStackTrace();
                    }
                });
                builder.build().load(URL).into(imgView);

The image URL looks something like this:

https://firebasestorage.googleapis.com/v0/b/<storage_address>.appspot.com/o/images%2Fprofile%2Fphoto%2F36805?alt=media&token=e62ec151-3aaf-4e5c-aefb-1b3c93828684

Could it be something to do with the token?

5
Do you get the URL passed to builder.build().load(URL) using StorageReference.getDownloadUrl()? If so, I don't know how changing the security rules would affect behavior. Access to the file through this URL is public--not controlled by the rules.Bob Snyder
I suspect the 403 error is not the result of the image download, but something else, such as your call to get the download URL. Post the code you use to get the URL.Bob Snyder

5 Answers

43
votes

Probably comes too late, but maybe helpful for someone else. I had the same issue, my problem is that filenames in firebase storage are unique. If you upload a new file with the same filename it will override the old one and generate a new token for it, making the old url obsolete. You should generate a unique filename for your uploaded file and then it should be fixed.

13
votes

If you are just testing Storage you might not have implemented Authentication. By default Storage expects uploading user to be authenticated. To by-pass that, in the Storage->Rules write this :

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth == null;
    }
  }
}

Worked like a charm for me. Have fun using Firebase

11
votes

You get the following error if the extension of your file is either incorrect or missing:

 {
    "error": {
    "code": 403,
    "message": "Permission denied. Could not perform this operation"
    }
 }

In the image URL you provided there is no extension for the image after the image name.

I have tested with one of my urls, this works (you can test): https://firebasestorage.googleapis.com/v0/b/training-a0a3e.appspot.com/o/penguin-56101_640.jpg?alt=media&token=8dfb913d-e2f3-4956-bd3a-2c3746d0d6d3

However when the .jpg is removed: https://firebasestorage.googleapis.com/v0/b/training-a0a3e.appspot.com/o/penguin-56101_640?alt=media&token=8dfb913d-e2f3-4956-bd3a-2c3746d0d6d3

The following response is received:

 {
    "error": {
    "code": 403,
    "message": "Permission denied. Could not perform this operation"
    }
 }
1
votes

Granting read access to everyone got my app displaying images correctly again:

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read: if true; 
      allow write: if request.auth!=null;
    }
  }
}

Probably this is not recommended, but solved the problem for the time being

0
votes

I had the same problem as you. This is a late answer but maybe this can help someone.

The problem for me was exactly as user2555964 described.

I can see that you only provide the url and it is referencing a token. I assume that you don't download the url from a storage path like this and just keep the reference in the database.

My problem in detail was that upon uploading a picture I saved the url and kept it in the database and then I had a storage trigger that optimized the picture on firebase cloud functions (copy, optimize, and replace original) which changed the token of the picture, making the token on the url worthless when checking for auth on storage rules.

The solution for me was to store the storage path instead and download the current url with the correct token.