'How to secure files upload on Firebase Storage, using an allow list?
Firebase Storage has a great example on how to secure file upload through their security rules feature:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /images {
// Cascade read to any image type at any path
match /{allImages=**} {
allow read;
}
// Allow write files to the path "images/*", subject to the constraints:
// 1) File is less than 5MB
// 2) Content type is an image
// 3) Uploaded content type matches existing content type
// 4) File name (stored in imageId wildcard variable) is less than 32 characters
match /{imageId} {
allow write: if request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*')
&& request.resource.contentType == resource.contentType
&& imageId.size() < 32
}
}
}
}
But what if you want to allow more files (not just images?).
Solution 1:[1]
The matches method in request.resource.contentType.matches('image/.*') accepts a regex as per Firebase Documentation, so you could do something like this:
request.resource.contentType.matches('image/jpeg|image/png|image/gif')
If you think you gonna have a long list of mime-types, you should probably start using custom functions in your Firebase Rules. Here's the same example from above, with custom functions and much more mime-types:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /images {
// Cascade read to any image type at any path
match /{allImages=**} {
allow read;
}
// Allow write files to the path "images/*", subject to the constraints:
// 1) File is less than 5MB
// 2) Content type is an image
// 3) Uploaded content type matches existing content type
// 4) File name (stored in imageId wildcard variable) is less than 32 characters
match /{imageId} {
// True if the uploaded file is part of the allow-list
function isAllowedFile(request) {
// Mime-types list source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
let allowList = "audio/aac|application/x-abiword|application/x-freearc|image/avif|video/x-msvideo|application/vnd.amazon.ebook|application/octet-stream|image/bmp|application/x-bzip|application/x-bzip2|application/x-cdf|application/x-csh|text/css|text/csv|application/msword|application/vnd.openxmlformats-officedocument.wordprocessingml.document|application/vnd.ms-fontobject|application/epub+zip|application/gzip|image/gif|image/vnd.microsoft.icon|text/calendar|image/jpeg|application/json|application/ld+json|audio/midi|audio/x-midi|audio/mpeg|video/mp4|video/mpeg|application/vnd.apple.installer+xml|application/vnd.oasis.opendocument.presentation|application/vnd.oasis.opendocument.spreadsheet|application/vnd.oasis.opendocument.text|audio/ogg|video/ogg|application/ogg|audio/opus|font/otf|image/png|application/pdf|application/x-httpd-php|application/vnd.ms-powerpoint|application/vnd.openxmlformats-officedocument.presentationml.presentation|application/vnd.rar|application/rtf|application/x-sh|image/svg+xml|application/x-tar|image/tiff|video/mp2t|font/ttf|text/plain|application/vnd.visio|audio/wav|audio/webm|video/webm|image/webp|font/woff|font/woff2|application/vnd.ms-excel|application/vnd.openxmlformats-officedocument.spreadsheetml.sheet|application/xml|application/vnd.mozilla.xul+xml|application/zip|video/3gpp|audio/3gpp|video/3gpp2|audio/3gpp2|application/x-7z-compressed";
return request.resource.contentType.matches(allowList);
}
allow write: if request.resource.size < 5 * 1024 * 1024
&& isAllowedFile(request)
&& request.resource.contentType == resource.contentType
&& imageId.size() < 32
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
