Real time chat in PHP +Redis +Pub/Sub +WebSockets (+NodeJS)
Asked Answered
D

3

3

I want to develop real time chat with channels and these are my needs:

  • PHP backend to manage site
  • Redis as session and data primary storage
  • Pub/Sub to send messages only to channel's interested users
  • one WebSocket connection with which the messages will be send and received.
  • (optional) NodeJS to use great npm packages like timesync or socket.io

I see two different architectures to achieve this:

  • with Socket.io

    socket.io

  • with Crossbar.io

    crossbar.io

These are my questions:

  1. Which architecture I should choose and why?
  2. The key is the user id cannot be obtained from client, because it can be malformed. So in the first architecture I think on every socket message I should attach PHPSESSID value from cookie and on sever-side retrieve PHP session from Redis. Am I right or there is better way to get user id?
  3. I wonder if getting user id in second architecture can be done differently?

Edit:

I choosed Crossbar.io, cause it is very powerful and allows to communicate many different language applications in real time. After studying examples, I come up with this:

  • On every login user have generated secret key in database.

  • PHP client (Thruway) connect to Crossbar server and register custom WAMP-CRA authenticator

  • User's browser connect to Crossbar server and is challenged. Secret and auth_id (user id) are loaded from DB with page load, so it can accomplish challenge and send response.

  • PHP authenticator search in DB for user with provided secret and id equal to auth_id. If there is, then it successfully authenticate session. Now we can trust that auth_id is real user id.

These are my question:

  1. How I can get auth_id on subscribe?

  2. I also added cookie authentication and browser is remembered after authentication. But when I look in Chrome DevTools there is any cookie nor value in local storage. Even after clearing cache my browser is still remember by Crossbar. I wonder how it is possible?

Edit2:

Maybe I was misunderstood, but the main question was choosing appropriate architecture and getting trusted user id. There was no attention so I awarded bounty and after that I was downvoted. I read a lot about real-time apps and finally decided to use Crossbar.io, so I edited question to be related to it. Then people started upvoting, proposing another architectures, but not really answering my questions. After all I managed to do it myself and presented my answer.

Deduction answered 8/3, 2017 at 8:52 Comment(6)
What do you mean by "PHP backend to manage site" ? I think your chat HTML interface don't really need to be served by a PHP backend. Then it becomes lighter, you can use either a nodejs or RatchetPHP backend to provide a chat server, and an HTML + js + autobahnjs front end.Terina
@Terina chat is only small part of site and I want to manage users, messages and other things from my PHP frameworkDeduction
There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue which can be answered in a few paragraphs. I would suggest you find a development forum (perhaps Quora?) to work out generalities. Then, when/if you have specific coding issues, come back to Stack Overflow and we'll be glad to help.Tengdin
@JayBlanchard I was expecting many general answers, but now I completely changed my question and it should be easier to answer.Deduction
The questions you ask in your edit are also quite broad.Tengdin
@JayBlanchard If anyone will not answer within bounty time I will just delete questionDeduction
D
2

About getting user id:

Every real-time chat examples which I saw, was getting id from client. It is unsafe, because client easily can manipulate it, so I needed to find another method. After reading WAMP specs I finally figured out that I have to authenticate user not only in app, but also in Crossbar.io. I choosed the dynamic WAMP-CRA method and implemented as following:

  • PHP app connect to Crossbar server and register custom authenticator (similar to example)
  • After user login in app there is generated secret key for him and saved in database. After logout, key is destroyed.
  • Workflow:

    1. Every loaded page contain user id and secret key loaded from db:

      <script>
          auth_id = '<?php echo $user->id ?>';
          secret_key = '<?php echo $user->secret_key ?>';
      </script>
      
    2. User browser connect to Crossbar.io server and get response with challenge from custom authenticator.
    3. It calculate signature using key and send along with auth_id to Crossbar.io server
    4. Authenticator gets from DB secret for provided auth_id and calculate signature. Then signatures are compared and if they are equal then authentication is successfull.
    5. Now auth_id contain user id and we can trust its value. Now you can refer section 'How I can get auth_id on subscribe?'.

Answers:

How I can get auth_id on subscribe?

By default publishers and subscribers does not have any knowledge about each other, but documentation show there is option to change it by configuring disclosure of caller identity. Then you can get auth_id from callback details:

  • PHP:

    $onEvent = function ($args, $argsKw, $details, $publicationId) use ($session) {
        $auth_id = $details->publisher_authid;
        ...
    }
    $session->register('com.example.event', $onEvent);
    
  • JS:

    function on_event(args, kwargs, details) {
        auth_id = details['publisher_authid'];
        ...
    }
    session.subscribe('com.example.event', on_event);
    

I also added cookie authentication and browser is remembered after authentication. But when I look in Chrome DevTools there is any cookie nor value in local storage. Even after clearing cache my browser is still remember by Crossbar. I wonder how it is possible?

First of all, clearing cache and hard reload does not remove cookies. When I was asking this question there was any cookie presented, but today I can see cbtid: cookies There was Chrome update two days ago, so maybe this was caused by bug in previous version.

Deduction answered 19/3, 2017 at 13:29 Comment(0)
A
1

I deeply light Streamer which is used by NASA to forward truck loads of data per second.The most reliable server for real-time messaging. Power web, mobile, tablet, desktop, and IoT apps.

Optimized data streaming for web and mobile. Lightstreamer enables several forms of real-time messaging. It is flexible enough to be used in any scenario, including mission critical applications. ► Real-time Data Push and Web Sockets ► In-App Messaging and Push Notifications ► Pub-sub with fan-out broadcasting and one-to-one messaging ► Firewall and proxy friendly ► Adaptive bandwidth throttling

As for your first question to get the auth_id on subscription , just monitor connection subscriptions then store tier upon successful connection. Also cookies are not recommended , use jwt.JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.Authentication is one of the big parts of every application. Security is always something that is changing and evolving.JWT helps you solve that concern.Since it is stateless.

Archaeology answered 18/3, 2017 at 11:58 Comment(1)
If you had came up with LighStreamer with JWT before I chose architecture, I would have accepted your answer. But you do it after my question was related to it Crossbar.io.Deduction
B
0

PHP Ratchet is one of the best implementations I've used for real-time communications via WebSockets. Its based on ZMQ Sockets which is used in several online gaming applications and chat applications.

The following examples will get you started pretty quick and will answer your questions around auth_id and subscriptions:

http://socketo.me/docs/hello-world

http://socketo.me/docs/push

Overview of the Architecture:

http://socketo.me/docs/push#networkarchitecture

I would advice creating individual connections(toppics) per conversation as it doesn't really take a hit on performance and will add an additional layer of security per chat.

Biotic answered 17/3, 2017 at 10:13 Comment(1)
Examples which you provided are basing on form/ajax submission, so this does not fulfill my need: "one WebSocket connection with which the messages will be send and received".Deduction

© 2022 - 2024 — McMap. All rights reserved.