I use flutter with firebase to save my images, and I use my app as an authenticated firebase user.
Rules first use case:
rules_version = '2';
firebase.storage service {
match / b / {bucket} / o {
match / {allPaths = **} {
allow read, write: if true;
}
}
}
Here, to display the images I can use the download url of the photos using:
await ref.getDownloadURL ();
example:
https://firebasestorage.googleapis.com/v0/b/project_name/o/images%2Fimage_name.jpg?alt=media&token=TOKEN
But also I can use the direct url of the photo (without token) and it works perfectly.
example:
https://firebasestorage.googleapis.com/v0/b/project_name/o/images%2Fimage_name.jpg?alt=media
Rules second use case:
rules_version = '2';
firebase.storage service {
match / b / {bucket} / o {
match / {allPaths = **} {
allow read, write: if request.auth! = null;
}
}
}
here I can use await ref.getDownloadURL ();
but i can't use the image url (hard coded)
My question :
why we use the rules of firebase storage (if request.auth! = null;) if the ref.getDownloadURL () is accessible even in a private browser and it does not require an authenticated user, however the url of the image (without token) is not accessible even if you are a firebase authenticated user?
That's just the way that download URLs work. They are designed to bypass all security rules. Rules only apply the code running in web and mobile apps that use the Firebase SDK to read and write data in the storage bucket. If you don't want full public access to a file, then don't use a download URL.
Related
I have a channel for communication between two users and I use Firebase storage to transfer files between these users.
I don't want a third user to have access to the channel's files.
I'm trying to identify authorized users using 'authfile' and the metadata inside it.
That authfile is uploaded using admin sdk.
Only specific users can download and upload files to specific path in storage where the authfiles metadata contains his uid. still the users are not allowed to touch the authfile.
The metadata inside the authfile looks like this:
metadata: {
AvnYaUFdaJh1j0FMIiKWoIC2MDw1: true, // firebase userId 1
YhFyYRbutlf1PFI4NLKTN4qWRhQ2: true, // firebase userId 2
}
my storage
The rules I've tried:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
// Channel Media
match /media/{channelId}/{allPaths=**} {
function isAllowedUser(uid) {
return /authfile.resource.metadata.users[uid] == true;
}
allow delete: if isAllowedUser(request.auth.uid)
&& request.resource.contentType != 'authfile'
allow read: if isAllowedUser(request.auth.uid)
&& request.resource.contentType != 'authfile'
allow write: if isAllowedUser(request.auth.uid)
&& request.resource.contentType != 'authfile'
&& request.resource.size < 16 * 1024 * 1024;
}
}
}
I am writing Firebase storage rules for the first time and would like advice on how this could be implemented.
I don't think you need 'users' here.
function isAllowedUser(uid) {
return /authfile.resource.metadata.users[uid] == true;
}
This should be valid
resource.metadata[uid] == true;
Additionally, if you need something like checking existence of another file or it's metadata, consider using Cloud functions as mentioned in this answer.
I get this error :
E/StorageUtil(21342): error getting token java.util.concurrent.ExecutionException: com.google.firebase.internal.api.FirebaseNoSignedInUserException: Please sign in before trying to get a token.
W/NetworkRequest(21342): no auth token for request
When I execute this code from https://stackoverflow.com/a/50877590/9272698 (to get the download url from an image with Firestore Storage) :
Future _getImageUrl() async {
final ref = FirebaseStorage.instance.ref().child('lake');
var url = await ref.getDownloadURL();
return url;
}
This is not due to my firestore rules since, I enabled it to be public like this :
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
Moreover I don't think it is due to internet connection since I'm able to load fields from Firebase Cloud Database.
Do you have a solution? Thanks a lot
I managed to get my url images.
Here's how :
Add SAH-1 certification to your project firebase and upload new google-service file to your project
Make your users sign-in anonymously (and enable it in your firebase project) before calling .getDownloadUrl()
so I have security rules like this:
service firebase.storage {
match /b/{bucket}/o {
match /eventPoster/{imageID} {
allow read: if isSignedIn()
allow create: if isSignedIn() && isImage() && lessThanNMegabytes(0.5)
}
function isSignedIn() {
return request.auth != null;
}
function isBelongTo(userId) {
return request.auth.uid == userId;
}
function lessThanNMegabytes(n) {
return request.resource.size < n * 1024 * 1024;
}
function isImage() {
return request.resource.contentType.matches('image/.*');
}
}
}
as you can see, I set only signed in user that can see/read the image. but if I copy and paste the link from my file in storage like below in incognito browser, I still can see my image
https://firebasestorage.googleapis.com/v0/b/XXXXXXX.appspot.com/o/eventPoster%2F0050370e-a226-4a69-a635-ceccce10007c?alt=media&token=44f6d5a4-ff44-4376-3c7b9dfac465
I expect that I can't see the image via the browser, I test it using google chrome. even though my app is for Android and iOS just for testing I use browser. I assume, I am not signed in if I access it via the browser
The URL you shared there is a download URL. That URL is publicly readable, regardless of security rules. The only way to stop it from working is by revoking its token from the Firebase console.
If you want a file in Firebase Storage to only be accessible in accordance to its security rules, don't generate download URLs for it, or at least don't share the download URL with anyone.
I have a firebase storage download url, like
https://firebasestorage.googleapis.com/v0/b/siren-5eee7.appspot.com/o/profile%2FC6jNlR0F4cZBPv7wF0REWUNVor33?alt=media&token=63a9130e-2ba6-4f38-ac3f-2231c54a1043
How can I access this url without token parameter?
For example, If I access above url without token there will be 403 error showing permisson denied.
My firebase storage secure rule is below :
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
This file located in /etc file. How can I do it?
Try changing rule:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read;
allow write: if request.auth != null;
}
}
}
In case you need the rule to allow accessing only the images without a token you have to do the following:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read: if request.auth!=null || resource.contentType.matches('image/.*');
allow write: if request.auth!=null;
}
}
}
From what I understand, you're trying to make the whole bucket publicly available. Using Firebase access rules might not be best, you might want to make the bucket read access available via Google Cloud's Storage layer.
To do that, one of the easiest way is using the Google Cloud Console Storage.
Select the bucket, click the bucket to configure and open the permissions tab.
Since this is Firebase managed bucket, it would have what Google called fine-grained access control. Don't worry, adding public access is quite simple.
Click Add members button, then, on the sidebar, add in allUser as new member, and give it the role of Storage > Storage Object Viewer. You can see more detail in the Storage Docs.
This will make the bucket publicly viewable via <bucketname>.storage.googleapis.com.
If you created extra bucket in Firebase that match a domain you own and verified in Google Search Console, you can create a bucket of named after your custom domain and have it publicly accessible using a CNAME of the custom domain that points to c.storage.googleapis.com. You can see more detail at Storage Endpoints Docs, Google Cloud's docs explain it much better than I can. Hope this helps!
If you need to access to certain url (image) without token parameter use the rule below:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /images/users/default.png {
allow read;
}
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
If you need to access to certain folder without token parameter use the rule below:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /images/{wildcardpath=**} {
allow read;
}
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Note: Change the url or folder to yours
I am trying to download images from Firebase storage but I am getting errors.
E/StorageUtil: error getting token java.util.concurrent.ExecutionException: com.google.android.gms.internal.zzanu: Please sign in before trying to get a token.
W/NetworkRequest: no auth token for request
However, I have my rules set up like this:
service firebase.storage {
match /b/<myappnameredacted>.appspot.com/o {
match /{allPaths=**} {
allow read, write;
}
}
}
Your rules are not like in the Firebase Storage Security Rules Documentation.
For make all your files public (for anyone), use :
// Anyone can read or write to the bucket, even non-users of your app.
// Because it is shared with Google App Engine, this will also make
// files uploaded via Google App Engine public.
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
For make all your files readable (for anyone), use :
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read;
}
}
}
You can also make only your image readable / writable, see the Firebase Storage Security Rules Documentation.