#How to add "x-" headers while connecting to Phoenix Channel using PhoenixJS client.
44 messages · Page 1 of 1 (latest)
with https, a TLS connection is established first before any HTTP traffic is ever sent, so everything is encrypted
yeah I don't think it's a totally bad instinct since sometimes the URL is more often logged than headers, but mostly that stuff is under your control however there isn't a way AFAIK to do it other than via params. Or, you could connect up unauthenticated, then send your token as a message and then assign current_user in your socket state to whatever you decoded from the jwt
or timeout and disconnect if you don't get auth message in $x time
i think Phoenix suggests using these short lived tokens for Channels but I havent used this approach https://hexdocs.pm/phoenix/Phoenix.Token.html
i think typically you only need this token for a few seconds because it's just used to establish the initial websocket connection
it looks like they encode the time they were created and you decide when you verify what you want to accept. the examples do use a day
if you wanted to use Token, you could have an api endpoint your frontend JS (presumably?) uses to swap out the JWT for a short lived token then connect the socket.
but that doesn't seem much nicer than connecting unauthenticated
you do get the timeout stuff for free
for folks using server rendered html they just use a meta tag
if they have a leaked JWT they own the whole system (as that user at least), I don't see how the threat is any different
like ideally you would just use an authorization header with your jwt right?
if they have a leaked jwt they would just use it there
well, you may not have control over or want to use the same long-lived JWT for your connection
if you have to use the URL like youre worried about
so to mitigate that concern using a Token with a shorter lifetime would help
gotcha, thought it might be a 3rd party service or something
you really just have the two options ultimately, url param, or unauth with a separate message to become authed
or contribute to Phoenix to use header 😅
yes
it's harder than it might look I think. because you have to get into cowboy and bandit to change how this works
like the connect contract doesn't have the headers accessible i dont think so you'd need to modify
yeah for js it would be simple enough
nice
Phoenix only gives you limited access to the connection headers for security reasons. WebSockets are cross-domain, which means that, when a user "John Doe" visits a malicious website, the malicious website can open up a WebSocket connection to your application, and the browser will gladly submit John Doe's authentication/cookie information. If you were to accept this information as is, the malicious website would have full control of a WebSocket connection to your application, authenticated on John Doe's behalf.
To safe-guard your application, Phoenix limits and validates the connection information your socket can access. This means your application is safe from these attacks, but you can't access cookies and other headers in your socket. You may access the session stored in the connection via the :connect_info option, provided you also pass a csrf token when connecting over WebSocket.
I noticed that the auth headers aren't allowed to be passed so you may want to research the security implications of this too
right but think about why they'd prevent you from just using bog standard Authorization header for this
https://devcenter.heroku.com/articles/websocket-security
Since you cannot customize WebSocket headers from JavaScript, you’re limited to the “implicit” auth (i.e. Basic or cookies) that’s sent from the browser. Further, it’s common to have the server that handles WebSockets be completely separate from the one handling “normal” HTTP requests. This can make shared authorization headers difficult or impossible.
So, one pattern we’ve seen that seems to solve the WebSocket authentication problem well is a “ticket”-based authentication system. Broadly speaking, it works like this:
When the client-side code decides to open a WebSocket, it contacts the HTTP server to obtain an authorization “ticket”. The server generates this ticket. It typically contains some sort of user/account ID, the IP of the client requesting the ticket, a timestamp, and any other sort of internal record keeping you might need. The server stores this ticket (i.e. in a database or cache), and also returns it to the client. The client opens the WebSocket connection, and sends along this “ticket” as part of an initial handshake. The server can then compare this ticket, check source IPs, verify that the ticket hasn’t been re-used and hasn’t expired, and do any other sort of permission checking. If all goes well, the WebSocket connection is now verified.
seems like this is what phoenix pushes for
can you even add the x header you want to the websocket request? this seems to say you cant
at least from a browser
all you get is url https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket
so maybe this ticket approach (with Token) is what you'd want instead of a long lived JWT
i do wonder why x headers was added though
well...probably nothing preventing them from being used with non-browser websocket clients like gun
but yeah still weird to only have x headers and seemingly no way to send from the browser
looks related to Nerves
you would need to encode the claims in the ticket too
or have a way to get another shorter-lived or specialized JWT for the wss connection
well it would protect against your initial concern, the URL getting logged out somewhere and there being a valid JWT that could be used across your app vs a short-lived (60 second?) token that only allows connecting to websockets
if it's just used for WSS connection then you could just use it as a param