How to add firebase database rules without authentication?
i want add Firebase Real-time database rules it is set to default and i cant use authentication because my app is already deployed with data in database.
please help, thank you
To grant any user complete read/write access to your Realtime Database (RTDB), you can use these global read/write access rules:
{
"rules": {
".read": true,
".write": true
}
}
These rules will allow anyone to read, write, delete or change the data in your database - including deleting the entire database. These rules will also trigger periodic emails from Firebase warning you that your rules are insecure.
Instead of using such wide-reaching rules, there are a number of ways you can tighten up your database to prevent such abuse.
Firebase Security Rules are documented here, their API reference is here and you can manage them here.
Because you have indicated that you aren't planning to use Firebase Authentication, I will omit those examples and instead refer you to the documentation for those examples. As you haven't provided any examples of data stored in your database, I will also be coming up with various examples around storing cars in a database.
Let's say your app contains a publicly accessible database of cars under /cars
with the following shape:
interface Car {
make: string,
model: string,
year: number,
type: string
}
Instead of using the completely public rules above, we can instead make it so users can only read/write to the /cars
node:
{
"rules": {
"cars": {
".read": true,
".write": true
}
}
}
With the above rules, you can create, update, delete any node under /cars
, but a read/write to /trains
would be denied. This is because security rules default to false
(deny) unless defined otherwise. If a security rule would throw an error (syntax error, missing data, bad object type), it is treated as false
(deny).
With the above rules, any user could create /cars/someId/path
and fill it with heaps of irrelevant data.
To correct this, we can define the nodes under a dynamic node path (such as cars/$carId
) and choose what fields will be read/writable:
{
"rules": {
"cars": {
// any car is readable
".read": true,
"$carId": {
"make": { ".write": true },
"model": { ".write": true },
"year": { ".write": true },
"type": { ".write": true }
}
}
}
}
Using these rules, you can now create and store a Car
object in your database. You won't be able to add data to locations like /cars/someId/path
but you can still add data to /cars/someId/make/path
like before.
This is where data validation rules come in. We can ensure that the type of a node is what we expect (as long as it's a number, string or boolean):
{
"rules": {
"cars": {
// any car is readable
".read": true,
"$carId": {
"make": { ".write": true, ".validate": "newData.isString()" },
"model": { ".write": true, ".validate": "newData.isString()" },
"year": { ".write": true, ".validate": "newData.isNumber()" },
"type": { ".write": true, ".validate": "newData.isString()" }
}
}
}
}
The above rules enforce the types of each part of a Car
object, but they don't make sure the entire Car
object is present. To enforce validation on the children of a node, such as making sure the entire car object is present, we move the ".validate"
rule up one level:
{
"rules": {
"cars": {
// any car is readable
".read": true,
"$carId": {
// a car object must be complete
".validate": "newData.child('make').isString() && newData.child('model').isString() && newData.child('year').isNumber() && newData.child('type').isString()",
"make": { ".write": true },
"model": { ".write": true },
"year": { ".write": true },
"type": { ".write": true }
}
}
}
}
With the above rules, you can now create/update/delete any cars stored under /cars
as long as they look like a Car
object.
Simply allowing complete write access may not be what you desire. By tweaking ".write": "true"
, we can apply additional restrictions on what data is allowed to be changed.
If we wanted to make it so you can only create/update a car, but not delete it, we can use:
".write": "newData.exists()"
If we wanted to make it so you can only create a car, but not update/delete it, we can use:
".write": "!data.exists()"
If we wanted to make it so you can only update an existing car, but not create/delete it, we can use:
".write": "data.exists() && newData.exists()"
Using these building blocks, you should now be able to tighten your database without blocking your existing application.