NotionCommotion Posted January 26, 2018 Share Posted January 26, 2018 Regular clients and super clients can connect to a socket server. Regular clients must initially register with the server and provide a valid unique ID. Super clients can tell regular clients what to do, but regular clients cannot tell other regular clients what to do. The super clients have short lifetimes and are initiated by authenticated human users via a webserver. How can the server determine which type of client has connected? Ideally, when creating the socket connection, I would be able to pass some authentication identification, however, it does appear that the ReactPHP class implements this functionality. As an alternative, I have several ideas. Have the super client first send a logon message and then the actual message as shown below. Basically the same, but have the username and password included in the intended message. $response=null; $msg=['message to send to the server']; $loop = \React\EventLoop\Factory::create(); $connector = new \React\Socket\TimeoutConnector(new \React\Socket\Connector($loop), 5, $loop); $connector->connect($serverIpPort) ->then(function (\React\Socket\ConnectionInterface $connection) use (&$response, $loop, $msg) { $connStream = new \DataLogger\Server\LengthPrefixStream($connection); $connStream->on('data', function($data) use (&$response, $loop, $connStream, $msg){ if(is_null($response)) { if(isset($data->success)) { $connStream->send($msg); $response==false; } else { $connection->close(); $loop->stop(); } } else { $response=$data; $connection->close(); $loop->stop(); } }); $connStream->send(['message with username and password']); $loop->addTimer(5, function() use (&$response, $loop, $connection){ $connection->close(); $loop->stop(); }); }); $loop->run(); Then the server can do something like the following for option 1, or check the received data for authentication to determine user type for my option 2. public function startServer() { $loop = \React\EventLoop\Factory::create(); $server = new \React\Socket\TcpServer($serverIpPort, $loop); $server->on('connection', function (\React\Socket\ConnectionInterface $conn) { $connStream = new LengthPrefixStream($conn); $connStream->on('data', function($data) use ($connStream){ $this->processMessage($connStream,$data); }); }); } private function processMessage($connStream,$data) { if(empty($connStream->type)) { //Allow regular or super clients to identify themselves only, and set the $connStream->type property accordingly } elseif($connStream->type=='regular') { //Allow regular client functionallity. } elseif($connStream->type=='super') { //Allow super client functionallity. } } Don't know for sure if either of these options are the "right" way of doing this, and would expect I am not the first one trying to do this and there are likely proven better solutions. Any recommendations? Thanks Quote Link to comment https://forums.phpfreaks.com/topic/306337-authenticating-socket-connections/ Share on other sites More sharing options...
gizmola Posted January 26, 2018 Share Posted January 26, 2018 If you are saying that you have role access, it seems to me that should not change the way your authentication works. There's no reason that you would want to make access a property of a connection. Access should be related to the individual user, and something you verify and grant/deny at the processing of every command/action. Quote Link to comment https://forums.phpfreaks.com/topic/306337-authenticating-socket-connections/#findComment-1555775 Share on other sites More sharing options...
NotionCommotion Posted January 26, 2018 Author Share Posted January 26, 2018 (edited) If you are saying that you have role access, it seems to me that should not change the way your authentication works. There's no reason that you would want to make access a property of a connection. Access should be related to the individual user, and something you verify and grant/deny at the processing of every command/action. Yes, I am saying I have role access. Not change the way my authentication works in what regard? Currently, I have zero authentication for socket connections and anyone can connect if they know the given IP and port. Why couldn't the connection be trusted after being authenticated that it was initiated by an authorized user? A shortcoming of my option 2 is it does not support JSON RPC batches very well. PS. Typo: it does NOT appear that the ReactPHP class implements this functionality. Edited January 26, 2018 by NotionCommotion Quote Link to comment https://forums.phpfreaks.com/topic/306337-authenticating-socket-connections/#findComment-1555778 Share on other sites More sharing options...
gizmola Posted January 26, 2018 Share Posted January 26, 2018 Yes, anyone can connect to a public server on a well known port. That isn't different from any other internet based application. What allows someone to proceed from connection to be able to actually use the socket connection? That is where you need to validate the user. This depends on how you have implemented authentication and session in your application. I would suggest you take a look at something built upon the foundation of JSON Web Tokens. There are a number of PHP libraries you can choose from: https://jwt.io/#libraries Here is an article on building something like this with Angular, but the concepts and problems JWT solve for you are likely the same. https://blog.angular-university.io/angular-jwt-authentication/ Quote Link to comment https://forums.phpfreaks.com/topic/306337-authenticating-socket-connections/#findComment-1555780 Share on other sites More sharing options...
gizmola Posted January 26, 2018 Share Posted January 26, 2018 I also found this article showing how build something with PHP: https://www.sitepoint.com/php-authorization-jwt-json-web-tokens/ Quote Link to comment https://forums.phpfreaks.com/topic/306337-authenticating-socket-connections/#findComment-1555781 Share on other sites More sharing options...
NotionCommotion Posted January 26, 2018 Author Share Posted January 26, 2018 Thanks gizmola, JSON web tokens appear to be a great option, and I will likely use them going forward. As I see it, they provide the following: User enters username and password and server returns a JSON Web Token. Future requests from user includes this JWT in the header so the server can authenticate. How would someone use them with sockets? I can pass them with every message, but the first example isn't technically valid JSON-RPC, and the second mixes application data with authentication data. Furthermore, both require both sides to adapt an additional custom agreement on protocol. And while I could and should use them for the HTTP client to HTTP server requests, what value do they plan in the sockets communication? Maybe I wasn't clear in my original post, but the "regular clients" do not use HTTP but naively communicate to the socket server using JSON-RPC. { "jsonrpc": "2.0", "method": "subtract", "params": { "subtrahend": 23, "minuend": 42 }, "id": 3, "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" } { "jsonrpc": "2.0", "method": "subtract", "params": { "subtrahend": 23, "minuend": 42, "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" }, "id": 3 } Quote Link to comment https://forums.phpfreaks.com/topic/306337-authenticating-socket-connections/#findComment-1555782 Share on other sites More sharing options...
kicken Posted January 26, 2018 Share Posted January 26, 2018 Your question doesn't really have anything to do with sockets. It has to do with the protocol being used to communicate, which is something entirely up to you to implement in whatever fashion you see fit. A socket connection is just a communications channel. As the classic analogy goes, it's nothing more than a pipe through with you can pass data. It doesn't care what data is sent, who's sending it, or who's receiving it. That's not it's job. If you want to control those details, then you implement that in your protocol and you make your applications require that protocol to communicate. If you permit multiple messages to be sent across the connection, then you can just have some separate authentication message that is sent first. { "jsonrpc": "2.0", "method": "authenticate", "params": { "role": "super" , "password": "blah" }, "id": 3 } Until the server sees that message, ignore or error on other types of messages. After the message is received, you know what the client is and can respond accordingly. If only a single message is allowed per connection then you'll just have to incorporate your authentication into that message in some way. Quote Link to comment https://forums.phpfreaks.com/topic/306337-authenticating-socket-connections/#findComment-1555784 Share on other sites More sharing options...
gizmola Posted January 26, 2018 Share Posted January 26, 2018 You could also add a required authentication token parameter to your your api calls. Quote Link to comment https://forums.phpfreaks.com/topic/306337-authenticating-socket-connections/#findComment-1555786 Share on other sites More sharing options...
NotionCommotion Posted January 26, 2018 Author Share Posted January 26, 2018 Your question doesn't really have anything to do with sockets. It has to do with the protocol being used to communicate, which is something entirely up to you to implement in whatever fashion you see fit. A socket connection is just a communications channel. As the classic analogy goes, it's nothing more than a pipe through with you can pass data. It doesn't care what data is sent, who's sending it, or who's receiving it. That's not it's job. If you want to control those details, then you implement that in your protocol and you make your applications require that protocol to communicate. If you permit multiple messages to be sent across the connection, then you can just have some separate authentication message that is sent first. { "jsonrpc": "2.0", "method": "authenticate", "params": { "role": "super" , "password": "blah" }, "id": 3 } Until the server sees that message, ignore or error on other types of messages. After the message is received, you know what the client is and can respond accordingly. If only a single message is allowed per connection then you'll just have to incorporate your authentication into that message in some way. Thanks kicken, I am good on the validating that the message is valid and provides the correct data, etc, and it does have to do with sockets. My assumption was that a socket connection that was once authenticated will always be authenticated and need not be authenticated again. The approach you showed is basically what I am doing. I also elected to require two transfers: one to authenticate and two for the single (today) data transfer. Quote Link to comment https://forums.phpfreaks.com/topic/306337-authenticating-socket-connections/#findComment-1555791 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.