3

I'm new to Firebase and trying to understand database rules. I'm using Firestore.

I have a database that basically needs to be read by all users, and also write. All users can see the documents in the database, and with certain actions they change certain fields. In certain cases they will detele certain old expired documents.

Now, I understand that I cannot leave read and write open to all, since this is not secure. So I am using authentication, I will anonymously authenticate the users, so that only authenticated users have access.

I understand this does the job:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth.uid != null;
    }
  }
}

Now, my question is, is this enough? I'm not a hacker, so I don't exacly know how a hacker would or could hack and detele/change stuff in my database, but does this mean that only changes can be made to the database through using the app? Could someone still hack this if they aren't using the app, and authenticate in some other illegal way.

Thanks so much for the help, I've tried to read to get to the bottom of this, but haven't managed.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
RJB
  • 1,704
  • 23
  • 50

2 Answers2

3

Firebase security rules can't limit access to a single app. All of the APIs are all available for public use for anyone who has an internet connection. They are all documented right here: https://firebase.google.com/docs/reference/rest/auth

The purpose of Firebase Authentication is to make sure that individual users have their individual access controlled appropriately. As soon as you let users create accounts using anonymous or email auth, they will have full access to all documents in the database with these rules. So, what you have right now is not really "secure" by most definitions of that word. You will have to decide if this is "secure" enough for your purposes.

You are also likely to get an email from Firebase saying that your rules are insecure. It's not a good idea to use /{document=**} like this, which matches all documents, which might not be what you intend. Minimally, you should call out the individual collections that you want users to access instead of using this global wildcard.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
2

Does this mean that only changes can be made to the database through using the app?

Anyone that can get your Firebase config elements could write a simple HTML page using the JavaScript SDK and try to interact with your Firestore backend. Note that it is not difficult to get your Firebase config elements, see at the bottom for more details.

This is why it is of upmost importance to implement a set of security rules if you want to protect your data.

Now, it is important to note the following point about Firebase Authentication and “registered“ users:

You should note that anyone can “create a new user in your Firebase project by calling the createUserWithEmailAndPassword() method or by signing in a user for the first time using a federated identity provider, such as Google Sign-In or Facebook Login” (if these identity providers are activated, of course). See the doc.

So, again, with your Firebase config elements, someone can easily build an HTML page that calls the createUserWithEmailAndPassword() method.

This means that if you want to limit the access of your app to some specific users just by using allow read, write: if request.auth.uid != null in your Firestore security rules, it is not sufficient.

One possible approach is to use Custom Claims. You can for example, set a specific claim to all your authorized users (e.g. authorized = true) and adapt your security rules to check the existence of this claim in the user token.


Note: How to find the Firebase config elements of a web app?

It is not really difficult to find the Firebase config object. Just look in all the HTML or JS files composing the app for the apiKey string.

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • Thanks, if I understand correctly. Could I use "custom claims", that when a user "signs up" through the app, I make a dummy field, like "userIsGenuine = true". Then I make in the firestore rules that only a user with the field "userIsGenuine = true", can read a write database. Will this stop, anyone who createUserWithEmailAndPassword from a simple html page? – RJB Mar 08 '20 at 20:33
  • 1
    "Will this stop, anyone who `createUserWithEmailAndPassword` from a simple html page" -> No it will not stop malicious users to use the `createUserWithEmailAndPassword()` method to create users but those users would not have the Custom Claim that is used in your security ruels and therefore they will not be abel to access your data. – Renaud Tarnec Mar 08 '20 at 20:39
  • You may be interested by reading the following [article](https://medium.com/firebase-tips-tricks/how-to-create-an-admin-module-for-managing-users-access-and-roles-34a94cf31a6e) which explains how to build a module which allows end-users with a specific Admin role creating other users and assigning them other specific user roles. It is not exactly what you are looking for but most of the concepts used there apply to your case in one way or the other. (*disclaimer, I'm the author*) – Renaud Tarnec Mar 08 '20 at 20:39
  • I've added the link, it was missing. Pls refresh the page to see the update to my comment. – Renaud Tarnec Mar 08 '20 at 20:41
  • 1
    Great, this is exactly what I needed. Can I use "custom claims" with anonymous log in also? – RJB Mar 08 '20 at 20:44
  • "Can I use "custom claims" with anonymous log in also"? Good question! I've never tried but I guess yes, since you have a user id (`uid`) for any Anonymous user. But to be confirmed. – Renaud Tarnec Mar 08 '20 at 20:47
  • 2
    It's not even really that someone can inject JavaScript into a web page. All of the API endpoints that are used by Firebase Auth are essentially available for direct public use. They don't need to be invoked by the provided SDK. They are even documented right here: https://firebase.google.com/docs/reference/rest/auth – Doug Stevenson Mar 08 '20 at 22:15
  • Can I set custom claim from Android side, or do I need cloud functions? – RJB Mar 11 '20 at 18:26
  • Custom claims should be set from a privileged server environment by the Firebase Admin SDK”. With “privileged server environment” the doc means a server that you fully control or a Cloud Function in your Firebase Project that runs back-end code (and that you also control, since it is in your own Project). – Renaud Tarnec Mar 11 '20 at 18:31
  • @RJB if you think my answer helped you, please upvote it. Thanks. – Renaud Tarnec Mar 11 '20 at 18:31