What do params do in case of socket connections?

Hi,

trying to understand the role of “params” in case of socket connections. Looked through the docs, the forum and Google, but still not quite clear on this yet.

In case of “regular” (i.e. non-websocket) http requests, params simply seem to be the request parameters supplied via URL or POST request, stored in “params” by Phoenix behind the scenes (at least initially).

Is this the same in case of socket connections?

Thank you for your thoughts!

:wave:

If you mean the params passed to the Socket object

// on the client                             |--goes to the backend--|
let socket  = new Socket("/socket", {params: {token: window.userToken}})
socket.connect()

then yes, they go straight to the connect/3 callback:

# on the backend
#           |-from the client-|
def connect(%{"token" => token}, socket, _connect_info) do
  # token here is passed from the client
end

https://hexdocs.pm/phoenix/channels.html might be helpful.


Off-topic:

AFAIK, the params are encoded into the query string, so they can’t be too large, since the URL length is sometimes suggested to be under 2048 characters (there might be limits by the browser? by the web server? both? not sure).

So the client connects to a URL like ws://example.com/socket/websocket?vsn=2.0&token=some_token_sent_from_client and the backend just decodes the query string and passes it into connect/3.

2 Likes

Due to that it is also important to remember, that there should be no secrets in the socket params, as this is sent as a part of the URL.

1 Like

Does it also apply to the connections over TLS? I somewhat blindly believe that everything other than the host – example.com in my example above, – is encrypted over TLS.

But it probably makes sense to avoid putting passwords in there since it can (?) end up in the browser history if longpoll transport is used instead of websocket

I’ve just read https://stackoverflow.com/questions/499591/are-https-urls-encrypted

In theory yes, but (there are always buts):

  • Long tokens will cause longer message to be sent to the server - you leak information which connections are authenticated
  • When you send token via JS you need to store that token in some place that is accessible for JS (for example Local Storage), which makes you susceptible to XSS side-channel attacks

So in general I would generate short-lived token (like 1m) that is fetched just before connecting and then it is sent to the browser as an authentication and isn’t stored anywhere. The token fetching happens over regular HTTP session with http-only cookie.

3 Likes

I agree here, although I have a word of caution about fetching before connecting. If all clients reconnect at once (or in a few seconds window), then you can end up sending a ton of requests to whatever provides your authentication service. For example, the equivalent of 1.2m rpm was being sent to our server when we did this, and it wasn’t specced for that.

One technique to avoid this is to always have a short lived token available. I use a 10 minute token that is fetched every 5-9 minutes to avoid thundering herd effect.

2 Likes

Thank you all, you really helped clear up my thinking around socket params! Not to mention the best practice thoughts around tokens :slight_smile:

4 posts were split to a new topic: Off topic posts: What do params do in case of socket connections?

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)