Exploring

Firebase cloud messaging large text and file sharing hack

noras noras |

Tags: #Firebase #PHP

This article describes a way to use of php as a middleware for passing text data that is larger than the firebase limit which is 4kb.

Firebase cloud messaging is one awesome tool that one can use to deliver information to client endpoint without even thinking about delivery costs and server load. However, last week I was working on a small project where I wanted to record a small audio file, convert the file to a bas64 text then multicast it to a group that is subscribed to a certain event.

After struggling with a problem that my base64 text never reached the end clients, I found out that was because the file was too big. Even when it was less than a second long audio recording.  That’s when I decided to use a middle man which will be PHP to hold the encoded text temporary until other clients fetch the contents. By temporary saving a base64 string for a file or the text in a session variable in php which can be summarised into 5 steps.

  1. Sender sends the large text to the web server that is running php. The server stores the text in a session variable
  2.  PHP sends the session id to the firebase.
  3. Firebase sends the session ID to the receiving clients
  4. The receiving clients sends a post request with the session ID to the web server.
  5. The web server sets the session ID and retrieves the saved variable and replies with the large text.

The PHP session hack

When calling the session_start() function in PHP it either starts a new session or resumes an existing session. The session stays alive for 24 minutes as a default value. When calling this method a session ID is generated that can also use to set a session that PHP was not able to track using cookies. We can get this session id by calling session_id() after calling the session_start() method. The cool thing is that we can use the same function to set the session id in order to access stores session variables.  Each session then can be used to store “session variables” that can be set like this $_SESSION[‘name’]=value

Handling client messages and forwarding to firebase (steps 2 to 4)

define( 'API_ACCESS_KEY', 'FIREBASE_FCM_TOKEN' );

if(!isset($_POST['operation']))
    throwError('Missing values operation');

$operation=$_POST['operation'];
$opcheck=($operation=='broadcast' || $operation=='get');
if(!$opcheck)
    throwError('Wrong values');


if($operation=='broadcast'){


$vcheck=(isset($_POST['topic_id']) && isset($_POST['payload']));

    if(!$vcheck)
            throwError('Missing values topic or payload');

    session_start();
    $_SESSION['payload']=$_POST['payload'];
    $_SESSION['ex']=time();

    $bmessage=new stdClass();
    $bmessage->sid=session_id();
    $bmessage->topic=$_POST['topic_id'];


    sendToFirebase($_POST['topic_id'],json_encode($bmessage));


}

function sendToFirebase($event_id,$message){
    $headers = array('Authorization: key='.API_ACCESS_KEY, 'Content-Type: application/json');

    $fields = array(  'to'   => '/topics/'.$event_id,
              'data' => array("message" =>$message) );

    #Send Reponse To FireBase Server
    $ch = curl_init();
    curl_setopt( $ch,CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send' );
    curl_setopt( $ch,CURLOPT_POST, true );
    curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
    curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
    curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
    $result = curl_exec($ch );
    curl_close( $ch );
    echo $result ;
}

Setting session id and replying (step 5)


if($operation=='get'){


  session_id($_POST['session_id']);
    session_start();

      if(!isset($_POST['session_id']))
            throwError('Session expired session_id');

    $scheck=(isset($_SESSION['payload'])  || isset($_SESSION['ex']));
    if( !$scheck )
        throwError('Missing values payload ex');

    $mins = (time() - $_SESSION['ex']) / 60;

    if($mins >2)
        throwError('Session expired');

    $bmessage=new stdClass();
    $bmessage->payload= $_SESSION['payload'];
    echo json_encode($bmessage);
}

About the author

noras

"Senior Software Engineer. MSc in Computer systems and Networks with big interest in security. Loves to play with Android code and does security research for fun and profit. Speaks 4 languages and codes in much more."

Related articles

Tags: #Firebase #PHP




Copyright © 2019 - nindoda.com