traviswingo
traviswingo

Reputation: 315

How can I prevent other sites/apps from accessing my Firebase?

I'm building a simple sample app that essentially just allows all users to the site to chat with each other, like a chat room. Firebase let's me authenticate users anonymously, which is what I want, since I only want users who are on my app to use it. The following code provides authentication as per Firebase docs:

var ref = new Firebase("https://<your-firebase>.firebaseio.com");
ref.authAnonymously(function(error, authData) {
  if (error) {
    console.log("Login Failed!", error);
  } else {
    console.log("Authenticated successfully with payload:", authData);
  }
});

That's cool. It works. Great. But here's my question.

What's to prevent someone from simply copying my javascript code from my sources and running their own app against my Firebase? Since the authentication method is on the client side within my app, one can simply copy-paste and start reading and writing onto my Firebase and modifying everything.

I have my rules set in my dashboard as such

{
  "rules": {
     ".read": "auth !== null",
     ".write": "auth !== null"
  }
}

I really am lost as to how secure this really is. I can't use secret tokens since it's all client-side. What am I missing?

Upvotes: 2

Views: 566

Answers (1)

japanitrat
japanitrat

Reputation: 86

Just create security rules that check whether the user has a certain attribute. You may set this attribute for your own user representation (let's call it "isAdmin") in the Dashboard once and then have all rules return true if the attribute is present and true.

Quick example:

{
  "rules": {
    // Allow everyone to read. This rule cannot be refined in deeper levels.
    // Once permission is granted at a certain level, it cannot be revoked
    // in a deeper level. However, the other way around works, as we see
    // next.
    ".read": true,

    // Always allow writes by users who have the isAdmin attribute. If this
    // evaluates to false, you can still have subrules in deeper levels that
    // may grant permission.
    ".write": "root.child('users/' + auth.uid + '/isAdmin').val() === true",

    "users": {
      "$uid": {
        // Users can write to their own entries, only. Except for the admin,
        // as his root rule already evaluated to true. The cascade is also
        // the reason why we need to check that the incoming isAdmin attribute is 
        // actually false. We don't want to give the user a blank cheque just
        // because he is himself ...
        ".write": "$uid === auth.uid && newData.child('isAdmin').val() === false",

        "isAdmin": {
          // No one can write this attribute, except users who already have
          // the attribute (see above). The cascade makes sure of that.
          ".write": false
        }
      }
    }
  }
}

Disclaimer: I did not test this extensively.

For more information, see https://www.firebase.com/docs/security/guide/securing-data.html#section-other-paths

Upvotes: 1

Related Questions