Passing session IDs in URLs is very bad practice, as it’s very common for them to be logged in all sorts of places. It’s not as critical as with regular HTTP request URLs that also end up in the browser history, but still, you should very, very much avoid it!
If both endpoints are on the same domain, then you could rely on the browser sending the session cookie alongside the websocket handshake request. Just make sure that you check the CSRF token in that case too, then it’s as secure as any other authenticated client request in your web app!
Alternatively use custom tokens to authorize the websocket connections, this will then also work in case the endpoints are on different domains. Usually one would use headers to pass them, the original RFC described that any additional headers are allowed in the handshake request, and it specifically mentions the Authorization header, because of course it does, someone with foresight wrote the RFC.
So, it’s back to submitting it via the URL, which sucks, but so is life. To minimize the possible attack surface, the token should be short lived, and one-time use only, which makes it already way safer than session IDs. It should be non-deterministically encrypted, and hold additional details such as the original Origin header, the client IP, or other client fingerprints, to make it as hard as possible to spoof the handshake request.
public function onOpen(ConnectionInterface $conn) {
parse_str($conn->httpRequest->getUri()->getQuery(), $query);
$sessionId = openssl_decrypt(hex2bin($query['session']), "aes-256-cbc", "your_secret_key");
session_id($sessionId);
session_start();
// Access session variables
$userId = $_SESSION['user_id'];
// Add client to clients list
$this->clients->attach($conn);
}
so no changes on middleware or bootstrap but it is important that the user who starts the WebSocket Server is equivalent to the user who starts the Apache server… otherwise you can’t get access to the session…
I was also doing WS on Ratchet and Cake + CakeDC Users plugins and my session is stored in DB. So I added user for WS with select only permission and manually parse session table looking for id.
I think I also do it bad thing like @ndm mentioned, but I couldn’t find better way.
Btw. my WS is as broadcast only, it not accept incoming data, only broadcast server messages to registered users (connections).
well i think its better to save the user id’s and connections in the cache instead of the database… I also figured out that it is better to set the session.cookie_secure = 1
session.cookie_httponly = 1 flags in your php.ini and provide the data through the http header: