Reputation: 1502
I store data in a Cloud Firestore database. Users in my app don´t need to create an account to get data and they can also write data without to login.
Google reminds me every few days that my database is insecure and can be abused by anyone. How can I improve it without accessing Auth variables?
My firebase rules
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
}
}
}
Is there a way to make my database more secure without using authentication?
The logic of my app:
My database contains surnames and their origin. If someone enters a name, he gets the origin back from the database. Example: "Doe" -> "Mexican". If the last name does not exist in my database, I call an API and save the value to my database. Every user needs both read and write permission.
What can I do here?
Upvotes: 15
Views: 12468
Reputation: 6354
Since the operation that you require writes for is limited (only inserting new items) you have some options:
Here is a sample node function that performs a write to a realtime database, and it succeeds when both read and write are false in the security rules (your associated package.json obviously needs to depend on firebase-admin and firebase-functions):
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();
let db = admin.firestore();
// This pushes the "text" parameter into the RDB path /messages/(hash)/original
exports.addMessage = functions.https.onRequest(async (req, res) => {
// Grab the text parameter.
const original = req.query.text;
// Push the new message into the Realtime Database using the Firebase Admin SDK.
const snapshot = await admin.database().ref('/messages').push({original: original});
// Respond to the user (could also be a redirect).
res.send('got it: ' + snapshot.ref.toString());
});
You may want to read about how the firebase admin SDK does access control but within a cloud function you should have admin rights by default.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read;
allow create;
}
}
}
Also, note this works for firestore (which you are using) but not for realtime database.
Obviously both of these methods could be in some way abused to write lots of data into your database, though the former gives you a lot more control about what is allowed (e.g. you could prevent more than N entries, or more than Y bytes per entry). The later still lets anyone create whatever they want.
Upvotes: 9
Reputation: 317392
The first thing is to start with the documentation. It's strongly recommended that you have an understanding of what rules can do, and translate that into requirements for your app.
What you're describing for your app right now is too vague to come up with good rules. To be honest, without Firebase Authentication, it's not possible to accept writes to a database without Authentication and also avoid abuse, since anyone could write anything from anywhere on the internet. This could also cost you large amounts of money if someone discovers your "open" database.
Upvotes: 7
Reputation: 276
Check out this documentation. https://firebase.google.com/docs/firestore/security/rules-structure. Configure the writing of unauthenticated users only in the collections you specify.
service cloud.firestore {
match /databases/{database}/documents {
// authentication required
function issignedin() {
return request.auth != null;
}
// authentication not required
function notAuthenticated() {
return request.auth == null;
}
// A read rule can be divided into get and list rules
match /cities/{city} {
// Applies to single document read requests
allow get: if notAuthenticated();
// Applies to queries and collection read requests
allow list: if notAuthenticated();
}
// A write rule can be divided into create, update, and delete rules
match /cities/{city} {
// Applies to writes to nonexistent documents
allow create: if notAuthenticated();
// Applies to writes to existing documents
allow update: if notAuthenticated();
// Applies to delete operations
allow delete: if notAuthenticated();
}
}
}
as a consideration, this will be insecure if the calling API allows indiscriminate writing. Note: If the API you are referring to is the only one you can write, you must configure only the reading as public
service cloud.firestore {
match /databases/{database}/documents {
// authentication required
function issignedin() {
return request.auth != null;
}
// authentication not required
function notAuthenticated() {
return request.auth == null;
}
// A read rule can be divided into get and list rules
match /cities/{city} {
// Applies to single document read requests
allow get: if notAuthenticated();
// Applies to queries and collection read requests
allow list: if notAuthenticated();
}
// A write rule can be divided into create, update, and delete rules
match /cities/{city} {
// Applies to writes to nonexistent documents
allow create: if issignedin();
// Applies to writes to existing documents
allow update: if issignedin();
// Applies to delete operations
allow delete: if issignedin();
}
}
}
Upvotes: 3