View Sidebar

Post Tagged with: Ephemeral Chat

EphChat: An Ephemeral Chat Program Written in PHP, JS + Firebase

EphChat: An Ephemeral Chat Program Written in PHP, JS + Firebase

I took a break from ReservationHop today to build a new chat program.

Screen Shot 2014-07-17 at 9.08.30 PM

EphChat, which stands for, you guessed it, “Ephemeral Chat,” is a chat program with a twist. No data is stored server side, and messages are only visible to participants for 60 seconds before they fade away into nothingness.

Anyone can create a new chatroom with a random URL hash, or can create their own chatroom.  Users are anonymous but you can edit your name if you wish. Messages are encrypted all the way to the server, where they are relayed to the chatroom participants and then immediately deleted. User sessions are stored until a user disconnects, then they are deleted, too.

Why did I build this?  Well, partly as an experiment with Firebase, but also because I like the idea of people being able to communicate in an encrypted, anonymous way without governments snooping on them.  Reporters can use this to do sensitive interviews; protesters under despotic regimes can use it to organize resistance.

The code is up on GitHub, which I felt was necessary to provide transparency into the app’s inner workings and security.  I don’t usually make my repositories public, for fear of being ripped apart by the hackersphere, but if anyone is going to use this app they’re going to want to know how it works.

I had a lot of trouble with Firebase’s security rules, but I think I figured it out.  Here’s the current security schema:

    "rules": {
      "rooms": {
        "$RoomId": {
          "connections": {
              ".read": true,
              ".write": "auth.username == newData.child('FBUserId').val()"
          "messages": {
            "$any": {
            ".write": "!newData.exists() || root.child('rooms').child(newData.child('RoomId').val()).child('connections').hasChild(newData.child('FBUserId').val())",
            ".validate": "newData.hasChildren(['RoomId','FBUserId','userName','userId','message']) && newData.child('message').val().length >= 1",
            ".read": "root.child('rooms').child(data.child('RoomId').val()).child('connections').hasChild(data.child('FBUserId').val())"
          "poll": {
            ".write": "auth.username == newData.child('FBUserId').val()",
            ".read": true

I welcome any and all feedback on the app, especially security.

Go ahead and start a new chatroom at!

July 17, 2014Comments are DisabledRead More