gsmlg
How to access http headers in Phoenix socket?
Can not get http header info from a Phoenix socket.
%Phoenix.Socket{
assigns: %{},
channel: nil,
channel_pid: nil,
endpoint: Web.Endpoint,
handler: Web.UserSocket,
id: nil,
join_ref: nil,
joined: false,
private: %{},
pubsub_server: App.PubSub,
ref: nil,
serializer: Phoenix.Socket.V2.JSONSerializer,
topic: nil,
transport: :websocket,
transport_pid: nil
}
Marked As Solved
rjk
Also don’t forget to actually enable sending those headers by configuring your socket on your Endpoint correctly as described here: Phoenix.Endpoint — Phoenix v1.8.8
So your Endpoint socket declaration should look like something like this:
# inside the file lib/my_app_web/endpoint.ex
#
socket "/socket", MyAppWeb.UserSocket,
websocket: [
connect_info: [:peer_data, :x_headers, :uri]
]
Now you should see those headers being forwarded inside the connect_info key during the connect callback as idiot described above.
Also Liked
idi527
rjk
Thinking about it, what you could also try if you still want to use the JWT token from the header, is to make a HTTP route that you land on as a user, authenticates the JWT and redirects to the socket path but this time with a phoenix token inside the query params. So instead of doing a GET on the socket path and directly upgrading to a websocket you go to a ‘basic’ route with the first GET, then you authenticate the JWT from the header, if OK you generate a phoenix token and redirect to your socket path with a query param set to that phoenix token (which is only valid for a short time (minutes)). One of the advantages of doing it this way is that error handling of the socket upgrades is almost non-existent (per the websocket RFC standard). Disadvantage is the extra ‘hop’ / redirect that you do extra but could be a small price given that websockets have a single authentication for the duration of the whole connection. Not sure if this works well with other transports, should work with at least Websockets as transport. (good point of LostKobrakai about the why behind all of this)
rjk
np, not too much offended about it other than seeing that specific comment under mine without context about something that’s running in production can seem a bit bad for others. Where the context should be that I’m using them in a way as where they are invented for (one-off or short-lived).
I made a simple test/dummy app which does the redirect (exchanging a JWT for a phoenix token that’s valid for only setting up the socket connection) But directly encountered that certain websocket clients don’t follow the redirect during the handshake (while the RFC standard says otherwise). So that route is also a bit bumpy and depends a lot on which client(s) you’re going to use.
Based on the above, another option is to not do the redirect and only make a plain REST endpoint on which you can exchange the JWT via auth headers for a short-lived phoenix token (that last one is pretty trivial to implement, counting 2-3 lines in total). Then you have the ‘safe’ part of using it within the header of the REST call and continue with a much smaller scoped and short-lived token for only making the socket connection via query params. One of the advantages of this approach is (as already mentioned) that you can handle authentication errors better.
Also went a bit deeper into looking how hard it is to add (cowboy) middleware before the endpoint as you already encountered putting a plug in front does not work. But this is not trivial and also seems way to hacky to be a valid approach for what you’re trying to achieve.
Another completely different idea (also seen in the wild) is letting clients connect unauthenticated to your socket and let them authenticate with a separate message as the first action after the connection is established, otherwise you just disconnect them. But given the info you’ve given so far this doesn’t work because you use a third party authentication that (i guess?) makes the request to your socket endpoint?
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
- #code-sync
- #javascript
- #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








