Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase Security rules for an app with multiple chat rooms

I am having trouble imagining what the security rules would look like for an application that looks like this:

  • One firebase with multiple chatrooms.
  • A moderator authenticates via a separate PHP application.
  • Moderators only have permission to modify their own chat room, they can read, write, update, and delete anything within their chat room.
  • Guests arrive and authenticate via the separate PHP application.
  • Guests have read and write access, but may not delete anything.

My questions right now are these:

  1. Is it possible to configure the rules to meet all these requirements? Or are there some requirements that cannot possibly be met?

  2. To what extent does the PHP Server have to communicate with Firebase, in notifying Firebase of the existence of users?

like image 464
Dave Mulder Avatar asked Jan 13 '23 18:01

Dave Mulder


1 Answers

First of all, check out this gist, which is an example I worked up some time ago for multiple chat rooms.

  1. Yes. It's perfectly possible.
  2. PHP Server? You don't need no server! :)

The data structure is basically as follows:

# chats roughly equal "rooms"
/chats/chat_id/users/...

# a timestamp of when each participant last viewed the room
/chats/chat_id/last/... 

# the messages sent
/chats/chat_id/messages/...

The security rules are self documenting. Here's a local copy for referential integrity.

{
  "chat": {
     // the list of chats may not be listed (no .read permissions here)

     // a chat conversation
     "$key": {

         // if the chat hasn't been created yet, we allow read so there is a way 
         // to check this and create it; if it already exists, then authenticated 
         // user (specified by auth.account) must be in $key/users
        ".read": "auth != null && (!data.exists() || data.child('users').hasChild(auth.account))",

        // list of users authorized to participate in chat
        "users": {
           // if the list doesn't exist, anybody can create it
           // if it already exists, only users already in the list may modify it
           ".write": "!data.exists() || data.hasChild(auth.account)",
           "$acc": {
              // for now the value is just a 1, later it could be a read/write/super privilege
              ".validate": "newData.isNumber()"
           }
        },

        // timestamps recording last time each user has read this chat
        "last": {
           "$acc": {
              // may only written by the authenticated user and if user is in $key/users
              ".write": "$acc === auth.account && root.child('chat/'+$key+'/users').hasChild($acc)",
              ".validate": "newData.isNumber()"
           }
        },

        "messages": {
           "$msg": {
              // to write a message, it must have all three fields (usr, ts, and msg)
              // and the person writing must be in $key/users
              ".write": "root.child('chat/'+$key+'/users').hasChild(auth.account)",
              ".validate":"newData.hasChildren(['ts', 'usr', 'msg'])",
              "usr": {
                 // may only create messages from myself
                 ".validate": "newData.val() === auth.account"
              },
              "msg": {
                 ".validate": "newData.isString()"
              },
              "ts": {
                 ".validate": "newData.isNumber()"
              }
           }
        }
     }
  }

}

A moderator authenticates via a separate PHP application. Use the custom login module to create a Firebase token for admins. Apply the security rules according to the data you store in that token.

Moderators only have permission to modify their own chat room... This should be pretty self explanatory by simply extending the user permissions above.

Guests arrive and authenticate via the separate PHP application. Use the custom login module to create a Firebase token for admins. Apply the security rules according to the data you store in that token.

(Or scrap the PHP app and just use Firebase's baked in authentication!)

Guests have read and write access, but may not delete anything. Use newData.exists() or newData.hasChildren(...) inside the ".write" rule to prevent deletion.

Guests cannot spoof other guests. Authentication tokens will prevent this

like image 189
Kato Avatar answered Mar 23 '23 11:03

Kato