I am using firebase and am trying to make the storage publicly accessible. According to the firebase documentation I need to include the following code, which I added to the .js file which contains a function that sends user input to storage.
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
Based off others' problems I've tried:
adding ;-s
changing it to firebase.storage(code),
doing var storage ...
but none of these methods work.
I have my code for configuring firebase (apiKey, authDomain, databaseURL, projectID, and storageBucket) and also initialized the app.
This isn't code that you would put in a JS file, this is a firebase storage security rule. It is a configuration that you would configure in the console for your project (alternatively, you can deploy the rules via the CLI, but they are still not a direct part of your application code).
You should navigate to the rules tab and input the configuration there:
Of course, the rule you are suggesting here is very dangerous!
This rule will allow any user (including unauthenticated users!) to write as much as they want into your storage bucket -- effectively giving you the bill for their free storage. You should consider carefully if this is what you really want.
Related
I want to use Azure Active Directory to allow users to read and write to Azure storage (specifically all Blobs and Tables) from a single-page web app.
I started like this:
import { InteractiveBrowserCredential } from '#azure/identity';
import { TableClient, TableServiceClient } from '#azure/data-tables';
const credentials = new InteractiveBrowserCredential({
clientId: myAuthConfig.clientId,
tenantId: myAuthConfig.tenantId,
});
const client = new TableServiceClient(
`https://${myAuthConfig.storageAccountName}.table.core.windows.net`,
credentials
);
client.listTables().byPage().next().then(console.log);
This works totally fine! I can see all the tables on the account. But then I wanted to list some of the data in on of the tables. So I did:
const client = new TableClient(
`https://${myAuthConfig.storageAccountName}.table.core.windows.net`,
'<table name>',
credentials
);
client.listEntities().byPage().next().then(console.log);
But this gives an error:
{
"odata.error": {
"code":"AuthorizationPermissionMismatch",
"message": {
"lang":"en-US",
"value":"This request is not authorized to perform this operation using this permission.\nRequestId:<uuid>\nTime:2021-10-28T18:04:00.0737419Z"
}
}
}
I'm very confused by this error. As far as I can tell I've done everything right. I followed every tutorial. I've set up active directory permissions for my app to use the storage API, my Microsoft account has permission to access the tables, OCRS is enabled, etc.
I'm not sure why I would have access to see a table but not see what's in it. I tried to use InteractiveBrowserCredential.authenticate to explicitly set scopes like this:
const scopes = ["User.Read"]
credentials.authenticate(scopes).then(console.log);
It works fine for User.Read but I couldn't figure out what scopes corresponded to Storage read/write access. If I added a scopy like "Microsoft.Storage" it told me that it didn't exist
Has anyone got an error like this before? What am I supposed to do here?
Thank you #gaurav mantri ,Posting your suggestion in comment as an answer.
From error it looks like your service principal does not have access permission to your table storage data. You should either grant permission using a RBAC role on the storage account resource (add to storage account contributors or readers) as below. Or use Storage Explorer to grant permission.
In your storage account please check, if you have Storage Table Data Contributer /Storage table data reader roles assigned as commented by #gaurav mantri
If not , you can add them
go into your storage account > IAM > Add role assignment, and add the special permissions
If roles are already assigned , the issue might be due to storage account being protected by firewall. Please try configure in Firewall and virtual networks of your storage account to add an existing virtual network or create a new vnet.If there is no issue you may allow access from all networks.
References:
Authorize access to tables using Active Directory - Azure Storage |
Microsoft Docs
Assign an Azure role for access to table data using powershell -
Azure Storage | Microsoft Docs
I am making a voice recording application in which the recording is saved in firebase storage in a folder named emailID (user email id when registered). I want that only the user can have access to that folder. Means that user can only open their own folder (matching name to their email). I want this feature to make my application more secure. I need the javascript code for the storage rules (according to my need) in firebase.
In this way, no one can get access to firebase storage until they log in, and after that, they can have access to their folder only.
It sounds like you're looking for this:
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "Zrecorder/<email>/path/to/file.txt"
match /Zrecorder/{email}/{allPaths=**} {
allow read, write: if request.auth.token.email == email;
}
}
}
Also see:
The Firebase documentation on properties in the request variable
I am building a NodeJS Express app and am using Firebase as the backend. I am trying to secure my firebase backend, more specifically the firestore database with Firestore Security Rules. However, I cannot seem to get my security rules to trigger.
I have a route called /api/goalPRs/:goalPRId which updates a database ref with the body of the request by calling
const goalPRsRef = db.collection('goalProgressReports');
goalPRsRef.doc(goalPRId).update(newGoalPR).then(()=>({update: 'Success'}));
Now, each goalPR has a field called targetGoalId, which I want to be constant, I dont want that data to be editable. Hence I have tried to set up the following firestore security rule.
service cloud.firestore {
match /databases/{database}/documents {
match /goalProgressReports/{goalPR} {
allow update: if request.resource.data.targetGoalId == resource.data.targetGoalId;
}
}
}
With this security rule I expect that any update to a document within goalProgressReport collection should be denied if the old targetGoalId is not equal to the new one. However, this is not the case. I can provide a new targetGoalId and it incorrectly updates.
Also, even when I try something like this with the security rules:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false
}
}
}
I am still allowed to write to the database, even though from my understanding this rule shouldn't allow any reads or writes to the database. Is my understanding of how security rules work incorrect? How can I fix my goalProgressReport security rule to not allow updates if the targetGoalId has changed?
Since you're running on nodejs, that means you're using either the Cloud Firestore node SDK or the Firebase Admin SDK which wraps the Cloud SDK. In this case, security rules don't apply. They only apply to access coming directly from web and mobile applications, and not from the server SDKs. The server SDKs always bypass all security rules, because it's coming from a privileged service account.
This question already has an answer here:
In Firebase security rules how can you stop hackers running a script for signup to your website? bare in mind I need them to be able to signup
(1 answer)
Closed 3 years ago.
Anybody who knows how to write scripts in Tampermonkey extension or how to create create extension can easily inject javascript code in webpage and access config keys. So how do you secure it?
var config = {
apiKey: "apiKey",
authDomain: "projectId.firebaseapp.com",
databaseURL: "https://databaseName.firebaseio.com",
storageBucket: "bucket.appspot.com"
};
firebase.initializeApp(config);
Right now only thing I can think of is wrap in anonymous function to avoid variable accessibility globally. which can prevent accessing variable.
It is still not secure, developer can ajax javascript file and parse data using regex, so how do you prevent it?
Another thing I thought of that is using nodejs as backend and use restapi to get data but it also exclude it being real time database. In addition I'd have to use socket.io to transfer data to client side in realtime if firebase update database in realtime in backend.
Because If anyone can inject script to access config keys can also read & write anywhere in database at his own will where read and write permission is granted.
which is a security concern. Any keys available on client is risky. so how do you prevent such attack?
This is a fairly common question. The answer is: no, a client cant write and read from everywhere in the database but only where your rules allow it.
This is exactly like REST, if you have a REST API then all your endpoints are public. What prevents mischief use are the server rules.
In this case, the database rules are in charge of securing and validating the data.
The simplest rule is user is logged in:
Items: {
.read: if auth != null,
.write: if auth != null
}
You can also have more common rules, like owner permissions
user_items: {
$uid: {
.read: if auth.uid == $uid,
.write: if auth.uid == $uid
}
}
The previous example considers a data structure where each user has its own node, but if for any reason you meant to keep it all in the same node it can be done using query rules. My recommendation would be to use the above structure, that way in the future, an admin feature can be added by denormalizing data.
The difference here is you are exposing your credentials if you take a look at them, there is nothing really private but only needed data for Firebase to match the request with your project, beyond that your project has to define the security. Please, take care of securing RTD, Firestore and Storage.
I am putting files in Firebase Storage, and (using cloud functions) store the objectMetaData.selflink in the database. I am trying to load a file using that link, but get a 401 stating that:
Anonymous users does not have storage.objects.get access to filename]
But since i am logged in (there is a currentUser on the auth() instance), i am confused what i am doing wrong here. Should i be sending some kind of token with my request?
I have not changed the initial ruleset for storage:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Also, maybe related but maybe not: since this example uses another approach, what is the difference between selfLink and getDownloadURL?
EDIT:
I finally got it working by using firebase.storage().ref(somePath). I also tried firebase.storage().refFromURL(selfLink).getDownloadURL() but that gave the error of supplying an invalid link to refFromURL. Then the question remains: what exactly is the selfLink?
Documentation states that the selfLink is the link to access the object, assuming you have sufficient permissions. It is not the download URL
Docs