How could you setup rules on Firebase which would allow a user to become a paid user of your app? For example, if I have the following data structure:
{
users: [
{
isPaid: false
},
{
isPaid: true
}
]
}
How could you setup firebase rules to not allow the user to update it themselves (by fudging a request), but still allow it to be updated automatically when they "pay" for your app?
I've thought about randomly generating a number and asking the user to enter that number or something like that, but I don't think that would work... Has anyone done something like this?
You'll need to have a server process that securely writes the paid flag using a Firebase secret (that can be found on Forge for your Firebase). Set the ".write" rule for /users/isPaid as false - the server code can bypass this rule since it knows the secret. You should call firebaseRef.auth(secret) from your server code first.
Related
I'm beginner and I'm developing a chrome extension that shows data received from my firebase realtime database. It does not need Login, or any personal information.
I'm trying to use REST API. Until now I have been in a test mode so I opened access to data for all. But Google keeps mailing me that I have to change the access rule because it is dangerous.
My present access rule is this:
{
"rules": {
".read": true,
".write": false
}
}
Now, I fetch data from https://<project name>.firebaseio.com/<database name>.json. But if I change the rule, the access will be denied.
So I want to add some key to the url and change access rule according to it so that I can fetch data from the url. For example,
https://<project name>.firebaseio.com/<database name>.json?some_key=<some_key>.
I do not need personal keys so I want only one key just like when we get information from open APIs. For example, when I use weather api, I get my api key from the host and adds the key to url.
Is this possible? If it is, I wonder two things.
the key that I can use (for example, realtime base wep API key)
access rule of realtime database
You can't pass parameters to the Firebase database like this:
https://<project name>.firebaseio.com/<database name>.json?some_key=<some_key>
But if you change the order of the values, it suddenly becomes possible:
https://<project name>.firebaseio.com/<some_key>/<database name>.json
We then change the security rules to only allow access when somebody already knows the secret key:
{
"rules": {
".write": false,
"$some_key": {
".read": true
}
}
}
Now the secret key is part of the path of the data, and only a user that already knows the key can read the data for that key.
I'm creating a web application using the Firebase Cloud Firestore, and I would like to write the security rules I've imagined, but I can't find any better documentation on this subject, it's always simple things, like check if the user is signed in.
So what I want to do is to check if the article that the client wants to read has a property called public, set to true. And maybe I can check the source of the request, to be sure it comes from my website's url ? I would like to find a solution to allow read without needing the user to sign-in , but also with a minimum of security.
And is it possible to return true if the property is undefined ? I would like to set the article public by default, but i don't know how to do it.
As Frank said, you cannot restrict access to Firestore from a specific domain. However and because you use some api key to call your firebase resources, you can restrict the use of this key to specific domain. You can do this by going to the GCP credentials page --> the API key you want to restrict. From there you can retrict how this key is used to websites, apps ...etc.
For you other question about checking if artice has public property, that can be done easily by use of security rules like:
service cloud.firestore {
match /databases/{database}/documents {
match /articles/{articleId} {
// I chose visibility as a prop here but it can be anything
allow read: if resource.data.visibility == "public"
}
}
}
To set the article as public by default you can do that from your client app when you create the article document itself by setting a property let's say "visibility" to public. something like this in your app:
// Add a new document with a generated id.
db.collection("articles").add({
visibility: "public"
...
})
I'm not sure if you can whitelist only your domain, but you can do pretty much everything you need with security rules
So what I want to do is to check if the article that the client wants to read has a property called public, set to true
allow read: if resource.data.yourPropertyName == "public"
I would like to find a solution to allow read without needing the user to sign-in
allow read: if true;
Keep in mind that those are not supposed to be used as filters, they are supposed to control who can write/read stuff
A manager needs to make the team's schedule live/public. The main challenge I'm running into is my firebase db security rules require users to be logged it in order to read data from it. They sort of look like this:
{
"rules": {
.read:true,
.write:true
}
"profiles":{
".read": true,
".write": true
},
"$clinicId":{
".write":"root.child($clinicId).child('permissions').child('admins').child(auth.uid).val() == true",
".read": "root.child($clinicId).child('permissions').child('members').child(auth.uid).val() == true"
}
}
}
What comes to my head is the following:
1- When the manger publishes the schedule, I would generate a token, add it to my permissions rules, and embed the token in the shared url as a param.
2- Then when an employee tries to access the url, I would use the token to sign in the user into the app.
I have explored claims and tokens in Firebase and I'm not quite sure which one would be the best neither this is a correct approach.
I would appreciate any insights.
Thank you in advance!
So it sounds like you want to make the data public, but harder to access.
Why don't you just include the id of the public doc in the url ? It is already a big-hard-to-guess hash. Which is all you'd be doing.
Additional security might include:
keep public docs separate from private ones, different collections
or use a flag on the doc that you can check the "visibility" of before returning to the client
I'm sure I'm missing something wrt Firebase Storage rules, but I've done the following:
STEP 1
Firstly I set the following Firebase Storage rule:
service firebase.storage {
match /b/{bucket}/o {
match /items/{dev_key}/{perm_id}/{file_name} {
allow write: if request.auth.uid == dev_id;
allow read: if request.auth.token.permId == perm_id;
}
}
}
I expected only signed in users with a custom claim permId matching the relevant location to be able to download the file, allow read: if request.auth.token.permId == perm_id;.
So, I then set a custom claim in Cloud Functions on a user as follows:
STEP 2
admin.auth().setCustomUserClaims(uid, {permId: '1'}).then(() => {
// send off some triggers to let user know the download is coming
admin.database().ref(`collection/${uid}/${itemId}`).update({
downloadReady: true
});
});
Then I signed the user out and signed back in again... which set the custom claims.
I checked that they were set in Cloud Functions as follows:
STEP 3
admin.auth().verifyIdToken(idToken).then((claims) => {
console.log("--------------claims -------------");
console.log(JSON.stringify(claims));
});
And I saw in the claims string... permID: "1"
On the client side I then requested a downloadURL (here is hopefully where I'm going wrong)... I expected this to not be the public download url but rather the download url that the Firebase Storage security rules will check:
STEP 4
var pathReference = storage.ref('items/<some-key>/1/Item-1');
pathReference.getDownloadURL()
.then((url)=>{
console.log("url: ", url);
})
The url I received from this call gave me this link
https://firebasestorage.googleapis.com/v0/b/emiru84-games.appspot.com/o/games%2FcfaoVuEdJqOWDi9oeaLLphXl0E82%2F1%2FGame-1?alt=media&token=45653143-924a-4a7e-b51d-00774d8986a0
(a tiny little image I use for testing)
So far so good, the user with the correct claim was able to view this image
I then repeated step 2, logout/login again, except this time with a permId of "0". I expected the url generated previously to no longer work since my user no longer had the correct custom claim... and the bucket location was still at the same location (bucket/dev_key/1/filename) but it still worked.
If I repeated step 4 I got a new url, which then gave the appropriate 403 error response. However the old url still worked (I guess as long as the token parameter is tacked on). Is this expected, if so, I'm not sure I understand how the Storage security rules make a difference if the download url is public anyway?
Any help clearing my foggy brain would be appreciated.
The download URL in Cloud Storage for Firebase is always publicly readable. It is not affected by security rules.
If you don't want to allow public access to a file, you can revoke its download URL.
I've recently built an app using Firebase as the data store and secured it using the security rules that only the user can read and edit their data which all works fine.
But now I want to build an admin section to list users and update details if need be, but the problem I'm running into is the fact that I cant access their data as I'm not the user. I'm seeing if its possible to allow read or write permissions to the user or admin?
UPDATE
Token generation
var tokenGenerator = new FirebaseTokenGenerator(authSecret);
var token = tokenGenerator.createToken({admin: true});
Security rule
".read": "auth.admin == true || otherauthmthod"
The method that you described above will work, assuming you update your security rules to look for the auth.admin bit. Alternatively, and likely a bit easier, is to generate an admin token, which will allow you to skip the execution of security rules entirely. This can be accomplished via:
var token = tokenGenerator.createToken({ any: "data" }, { admin: true });
See https://github.com/firebase/firebase-token-generator-node for more details.