-3

I have 2nd question for you.

I make a website in JS based on Firebase database. One piece of my code creates a point system. With function "set" code creates row "points" in database which contains number of gotten points (default 0). I want to increase number of them by 1 when user did "some action". In database rules I put a line which allows adding and getting values from "points" only to authorised accounts.

Well..

what would happen if somebody copied the code from me, changed adding-1-point code to adding-2000-points code and pasted it just after authorisation. Then he'll open the site on his localhost, authorise with his email and pw... Or he'll even make a Browser extension with that code. Would he get 2000 points more???

So how to fix that, hide or sth. I wonder for so long and i cannot find the answer. In MySQL it was more simple.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

2 Answers2

1

You can write security rules for pretty much any scenario.

If you only want to allow increments of 1, the simple basis is:

".validate": "newData.val() = data.val() + 1"

If you want them to be able to add or subtract 1:

".validate": "(newData.val() === data.val() + 1) ||
              (newData.val() === data.val() - 1)"

If you want to ensure that the user can only modify their own score by adding or subtracting 1:

"scores": {
  "$uid": {
    ".write": "auth.uid === $uid"
    ".validate": "(newData.val() === data.val() + 1) ||
                  (newData.val() === data.val() - 1)"
  }
}

And on and on. Some of the most advanced scenarios I've seen were rules to validate moves of a chess game (I can't find them right now, so am not sure if they were ever published outside of Firebase), and rules for a item trading in a multiplayer game.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • I think that code doesn't protect from adding code with script. I mean that someone authurised can do everything with database, so if i give your rules, he will be able to make script adding points 1 by 1 :/ – Hubert13888 Oct 21 '17 at 10:42
  • Am i able to add something to firebase using Php? It would be the most safe way (I use symfony framework). – Hubert13888 Oct 21 '17 at 10:47
  • I found https://github.com/kreait/firebase-php but i don't know where i can get google-service-account.json from – Hubert13888 Oct 21 '17 at 10:49
  • I think the problem the data structure and using Functions – cutiko Oct 21 '17 at 13:00
  • @Hubert13888 Repeated calls like that can be [rate limited in security rules](https://stackoverflow.com/q/24830079). What you can accomplish with security is really only limited by your own ability and imagination. While it may be easier to implement certain things in a custom server, the same can often be accomplished (in a less familiar way) using security rules. – Frank van Puffelen Oct 21 '17 at 14:56
0

The problem is the data structure, you don't want to allow each user from adding points directly because that will be abusable. You have to allow the users to state that they gave a point or take a point and then Functions have to increase the points. This should be your database structure:

{
  "objectsWithPoints":{
    "object1": {
    "attribute": "the value",
    "points": 2
  }
  "pointsForObjects":{
    "object1": {
      "uid1":true,
      "uid2": true
    }
  }
}

What you have to do for security is to write rules that allow the user only to write their own object inside the pointsForObjects node:

"pointsForObjects": {
  "$objectId": {
      "$uid": {
              ".write": "auth.uid === $uid",
              ".read": "auth.uid === $uid"
       }
  }
}

This way the user can say *"I give a point or I take a point "*if there is no data, allow in the UI to the user to give a point if there is data allow to the user in the ui to take down a point.

Finally, to update the points you have to set a listener using Functions, whenever something is written in the pointsForObjects node count each belonging to the object and set the count to the object.

This way there is no problem with if a hacker try to write "uid: false, or "uid": 1, because you are counting the childs. And any hacker can't add more than one child because it will be overwritten since the key is the same and can only be the uid.

cutiko
  • 9,887
  • 3
  • 45
  • 59