I have a very simple Firebase Storage structure:
> check-in-station-content
> reports
These are two folders and I am trying to set up a restriction on the check-in-station-content to accept only video/mp4 files, not bigger than 30MB and to be uploaded only by authenticated parties. So, my rules looks like this:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read: if request.auth != null;
}
match /check-in-station-content {
// Allow write files, subject to the constraints:
// 1) File is less than 30MB
// 2) Content type is video/mp4
match /{videoId} {
allow write: if request.auth != null && request.resource.size < 30 * 1024 * 1024 && request.resource.contentType.matches('video/mp4')
}
}
}
}
Then, when I go to the UI for the storage and click the Upload button, nothing is stopping me of uploading whatever file having whatever size
When you use the Firebase console, you actually bypass all the security rules, since you are interacting with Cloud Firestore as the owner of the project (or another role with similar access, e.g. Editor). The rules apply only when you are using one of the Client SDKs or the other Client APIs.
By the way, note that your rule matches the check-in-station-background-content path and no the check-in-station-content one.
Related
I just added new value to my users collection appVersion
My user collection like:
documents/users/5kwgNgGi3sY6oCbUAg9v
so i just added value versionCode to collection. if user download new app it will be update
My rule now:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth !=null
}
}
}
what i need as a if else statement
if(request.auth!=null){
firebase().collection('users').where('UID','==',request.auth.uid).get().then(x=>{
if(x.docs[0].versionCode==4){
allow
}
else{
deny
}})
else{
deny
}
There is no way to perform a query in your security rules, as that would never scale on the backend.
Instead, what you'll want to do is store the user documents with the UID as the document ID, so that the document you show is at path documents/users/xHzKoXbrZqbHZY8DI3wkXnMShF92. Then you can use get() in your rules to load the document, as shown in the documentation on accesing other documents in your rules.
I'd also recommend checking out the documentation on attribute-based and Role-based access, as it covers a pretty similar scenario.
I have setup my storage security rules to only allow authenticated users to post images that are less than 3mb with the following rule:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
// Only allow uploads of any image file that's less than 3MB
allow write: if request.resource.size < 3 * 1024 * 1024
&& request.resource.contentType.matches('image/.*');
allow read, write: if request.auth != null;
}
}
}
However, I just tested from my client and I was able to upload a picture that is 14mb. I have given plenty of time for security rules to set.
How did I bypass this rule?
While the other answers provided you with security rules you could use, it’s also good to add that you can test your security rules using the Firebase rules playground. Using this tool, you can tell exactly the resolution of each of your rules when tested against an event (create, read, update, delete).
I tested your security rules and received this output:
As you can see, while your file size limit rule is working fine, the broader allow write: if request.auth != null; rule is still letting your request go through. This is what the other answers pointed out and what is included in the documentation:
If any of the “allow” rules for the method are satisfied, the request is allowed. Additionally, if a broader rule grants access, rules grant access and ignore any more granular rules that might limit access.
Please see here:
In the case where multiple allow expressions match a request, the access is allowed if any of the conditions is true
So in your case:
allow read, write: if request.auth != null;
let the user to write files with any size.
I think this is the rule you want:
allow write: if request.auth != null &&
request.resource.size < 3 * 1024 * 1024 &&
request.resource.contentType.matches('image/.*');
allow read: if request.auth != null;
You also have allow read, write: if request.auth != null; which overrides the previous one. Try removing write from 2nd line:
match /{allPaths=**} {
// Only allow uploads of any image file that's less than 3MB
allow write: if request.resource.size < 3 * 1024 * 1024
&& request.resource.contentType.matches('image/.*');
allow read: if request.auth != null;
}
I'm trying to secure my Firebase (google cloud storage) files based on user data. In firestore, I use a rule based on getting database content (look up the uid in users table and match a field) and that's working fine. I'm trying to use the same kind of rules in firebase storage but in the simulator I get Error: simulator.rules line [12], column [17]. Function not found error: Name: [get].; Error: Invalid argument provided to call. Function: [get], Argument: ["||invalid_argument||"]. My rules look like this:
match /b/{bucket}/o {
function isAuth() {
return request.auth != null && request.auth.uid != null
}
function isAdmin() {
return isAuth() &&
"admin" in get(/databases/$(database)/documents/users/$(request.auth.uid)).data.roles;
}
function clientMatch(client) { // expects user's "client" field to be ID of client
return isAuth() &&
client == get(/databases/$(database)/documents/users/$(request.auth.uid)).data.client;
}
match /P/Clients/{client}/{allPaths=**} {
allow read, write: if isAdmin() || clientMatch(client);
}
}
}
Line 12 is the one beginning client == get, in clientMatch().
I haven't been able to tell whether these functions are only supported for Firestore (db) rules, or whether they should work for storage as well.
If this doesn't work, what are my options? How do people look up user data for Firebase storage security?
You currently can't reference Firestore documents in Storage rules. If you would like to see that as a feature of Storage rules, please file a feature request.
Consider instead using a Cloud Functions storage trigger to perform some additional checks after the file is uploaded, and remove the file if you find that it's not valid.
This is now possible with cross-service security rules. You have to use firestore. namespace before the get() and exists() functions as shown below:
function isAdmin() {
return isAuth() && "admin" in firestore.get(/databases/$(database)/documents/users/$(request.auth.uid)).data.roles;
}
Do note that you'll be charged for read operations just like in Firestore security rules.
I just installed FriendlyPix iOS and followed all the steps listed on the readme including deploying the cloud functions and rules. I am getting an error and I think it has to do with the storage rules. The error I get is:
User does not have permission to access gs://friendlypixsk.appspot.com/HS4uNP1BYNNnW2Qf59azZH8i3gp2/full/-LAoHLCCMnlD8RoFhUNd/jpeg.
This happens in the uploadPressed function in FPUploadViewController. It happens in the fullref.downloadURL function call. The closure passed to that function is getting an error.
The Firebase Storage rules I have are as follows:
// Returns true if the given UID matches the signed in UID,
// the uploaded file is an image and its size is below the given number of MB.
// Also allow deletes.
function isImageAndBelowMaxSize(uid, maxSizeMB) {
return request.auth.token.admin == true || (request.auth.uid == uid
&& (request.resource == null // Allow deletes
|| request.resource.size < maxSizeMB * 1024 * 1024 // Max size for the uploaded file
&& request.resource.contentType.matches('image/.*'))) // The file is an image
}
service firebase.storage {
match /b/{bucket}/o {
match /{userId}/thumb/{postId}/{fileName} {
allow read, write: if isImageAndBelowMaxSize(userId, 1);
}
match /{userId}/full/{postId}/{fileName} {
allow read, write: if isImageAndBelowMaxSize(userId, 5);
}
}
}
I have not modified them at all. The image does get uploaded and I can see it in the firebase console. I'm a little new to firebase and not sure exactly how these rules work. I have signed in using google sign in.
Any help would be greatly appreciated!!
Thanks
Regardless what I put in the read condition, I able to read the files
For example:
service firebase.storage {
match <firebase-storage-url> {
match /{userId}/{allPaths=**}{
allow read: if '1'== '2';
allow write: if true
}
}
}
Although 1 not equal 2 I able to read firebase storage files. How it can happens?