vipulbhj

vipulbhj

How to use Phoenix `socket` on localhost with React Frontend?

Hello, I am trying to build a Backend system in Phoenix, this is mostly APIs but needs Websockets for a chat interface.

I researched a bit with Claude, and found out that Phoenix sockets can be a great choice for this with Channels, so I create a setup as details below.

I have two tables

chat_sessions
chat_messages

When the user lands on /api/v1/chat/sessions, I check for a few things and then create a record in this table, and I use put_session to set the id of this table in a cookie and send it back to the client.

Now I created a socket endpoint in the endpoint file similar to /live just under /live

socket "/api/chat", ProfiWeb.UserSocket,
    websocket: [connect_info: [session: @session_options]],
    longpoll: false

Inside the UserSocket I added

def connect(params, socket, connect_info) do
    Logger.info("WebSocket connection attempt with params: #{inspect(params)}")
    Logger.info("Connect info session: #{inspect(connect_info[:session])}")
   
    with {:ok, session_id} <- extract_session_id(connect_info),
....
...


defp extract_session_id(connect_info) do
    case connect_info[:session] do
      %{"chat_session_id" => id} when is_binary(id) ->
        Logger.info("Found chat_session_id in session: #{id}")
        {:ok, id}

      _ ->
        Logger.info("No session found, checking params for session_id")
        {:error, :no_session_id}
    end
  end

Backend is running on http://localhost:4000 and FE is on http://localhost:4321

I was hoping this setup would be enough and I will get the cookie since inside session options, same_site is set to “Lax”

 @session_options [
    store: :cookie,
    key: "_profi_key",
    signing_salt: "4yRHL+9g",
    same_site: "Lax"
  ]

But when I check the request headers in browser, I don’t see the cookie, googling and going back and forth with Claude, finally landed on creating a reverse proxy on localhost:3000 and proxying both through that.

When I do that, browsers start sending the cookie, but the server still doesn’t get it.

I fought this problem a lot, with Claude a lot but nothing worked, added a ton of logs but nothing.

Does anyone know how I can do this ?

Thank you for your help, much appreciated :folded_hands:

Phoenix Forum > Questions / Help

EDIT: If I missed any details, please let me know, I will update the post with those details.

Most Liked

Nicodemus

Nicodemus

First, you’ve chosen one of the most difficult ways to architect a website on the modern web, owing mostly to a gauntlet of security measures you will have to properly configure and work with. What is your app, and does it require a completely separate front-end? Does it even require React? 90% of SPAs are over-engineered, fragile, and worse off for being SPAs instead of progressively enhanced classic web sites, mainly due to an over-indulgence in following trends and cargo culting.

Are you going to host it on two separate domains, as is implied by running two dev servers. If you instead configure Phoenix to serve all of your static assets, then you don’t need to configure CORS, or deal with cookies being set for two different domains (though sharing across subdomains is relatively easy.) You can still share a domain with two different services behind it, but then you’ll need an HTTP aware proxy/load balancer to know that “/api” requests go to the Phoenix cluster, and “/app” requests go to the front-end nodejs or whatever cluster. So my main question is, what are you building, and does it really require this complexity? None of it is impossible, but if you’re new to these things (assumed by use of LLMs for research, and generally for the kinds of questions you’ve asked here and on Discord, apologies if you’re not), then you might want to reevaluate trying to build something so complex without some experience with simpler setups.

Second, Phoenix.Socket will likely never allow you to access arbitrary headers or cookies as LostKobrakai said, due to Cross-Site Websocket Hijacking. This is a serious problem, and I agree with Phoenix’s hard-line stance to basically make it close to impossible to fall into this trap. There is no way around this other than implementing your own version of Phoenix Channels.

I’m honestly not sure why using a local proxy made the browser start sending cookies for the socket connection, but I suspect it was coincidental. Websocket() will send any set cookies, depending on the cookie setting. However, fetch() will not allow the server to set cookies. So if your FE is truly separate and you’re “landing on /api/v1/chat/session” with fetch(), the only way the session cookie could have been sent was if you manually made a request to your BE on localhost from your browser at some point, which set the cookie. However, if you do deploy this to two separate domains, then it’s going to be very difficult to get the session cookie from one domain to the other, anyways.

If you really want to have a separate FE and BE, on separate domains, then the simplest solution is to treat the FE like it’s a completely different application running in a completely environment. Don’t use session data or cookies at all, and instead follow the guide that Kapsy in Discord already sent you.

The only difference, is that instead of setting the token in the assigns and in the JS of the page (which works if phoenix serves your FE), you will need to make a fetch() request from the FE to the BE with authentication information to your API, which will return a token for the JS in the FE to use when connecting to the Channel.

BTW, none of this is the fault of Phoenix or Elixir… this is all due to the security requirements of the modern web, which has had to add a lot of hoops to jump through due to bad actors exploiting vulnerabilities like CSWSH and CSRF to hack web sites. That and your desire to create one of the most difficult stacks to build a web site with, requiring knowledge and experience across a wide swatch of technologies, protocols, and security standards to get right.

Where Next?

Popular in Questions Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
vegabook
I'm brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New

Other popular topics Top

chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I fore...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a &gt; b) do {:ok, "a"} end if (a &lt; b) do {:ok, b} end if (a == b) do {:ok, "eq...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 47849 226
New

We're in Beta

About us Mission Statement