#How to add "x-" headers while connecting to Phoenix Channel using PhoenixJS client.

44 messages · Page 1 of 1 (latest)

placid hill
#

not sure that you can easily. why do you think a header is more secure than a param?

#

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 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

#

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