ASCrookes
Phoenix Limit Sockets per user
Hello,
I have recently been working with Phoenix Channels. The whole process has been incredibly straightforward so far! The one thing I have not been able to find has been the security implications when using Channels/Sockets.
I would imagine in a production app with authentication one would want to limit both the number of sockets a single user can have open at once and the number of channels connected.
Currently we limit the number of sessions already so we could tie each user socket’s id to the access token and force disconnect when a session is closed, but that still wouldn’t stop a user from opening multiple sockets per active session.
If anyone can point me in the right direction or if my thinking is wrong about security here let me know!
Most Liked
chrismccord
You can intercept presence_diff in your channel and drop the message:
intercept ["presence_diff"]
def handle_out("presence_diff", _, socket), do: {:noreply, socket}
chrismccord
You can rewrite the topic yourself fwiw by intercepting, which is probably exactly what you’re doing
It’s not something I’m likely to support in Presence because we would have to track the event per subscriber which would add complexity.
Mazyod
Great question, and I’ve recently when through the exercise myself.
First, you have to understand that blocking multiple sockets at the user_socket level is nasty, since all you can do is return :error. The client socket then gets terminated, and has no clue if it is was an authorization error or multiple sockets error, or even perhaps some other logic you have to block the connection (in my case, client update required!).
With that being said, you might not care about returning the exact error to the user, or maybe you do:
-
If you do: You need to allow the user to connect to a socket, and then make it obligatory that all active users connect to some global channel (in my case it is
global:[USER_ID]). Once you accept the socket, and the user attempts to join this global channel, it becomes trivial to detect multiple sockets using Presence,:global.where_is, or Elixir v1.4 pid Registry.
I personally tried presence, but it ends up adding extra baggage like pushing presence state down to the client, which I don’t want. I was using:global.where_isbecause I am still stuck at Elixir v1.3, but it worked fine. -
If you don’t: Just use
:global.where_isor Registry to register the user socket under their user id, then check if a process exists when another socket connection comes in.
I’ll tell you this though, at the end, I scrapped it. The reason I wanted it in the first place was because a user would end up in a game room with themselves (given they connect on two different sockets). The best solution I found and implemented was to add the checks in the room channel and game channel level not at the socket level. If the user wants to connect on multiple devices, sure why not! The real problem is elsewhere and should be solved on a different level.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








