Phoenix.Endpoint.socket/3 is not configurable enough

From the Phoenix 1.6.15 docs…

  • {:session, session_config} - the session information from Plug.Conn. The session_config is an exact copy of the arguments given to Plug.Session. This requires the “_csrf_token” to be given as request parameter with the value of URI.encode_www_form(Plug.CSRFProtection.get_csrf_token()) when connecting to the socket. It can also be a MFA to allow loading config in runtime {MyAppWeb.Auth, :get_session_config, []}. Otherwise the session will be nil.

Emphasis:

This requires the “_csrf_token” to be given as request parameter

It looks like _csrf_token is hardcoded, which doesn’t jive with…

plug :protect_from_forgery, session_key: "_phoenix_sa_csrf_token"

Is there anyway around this?

Context is that dead mount/3 shows proper session, but connected mount/3 doesn’t.

Thanks for the help.

Connected mount does not use plug because it doesn’t go through an HTTP request cycle

Plugs only apply to full HTTP requests which is why you sometimes have “duplicate” functionality in Plugs and Live Hooks

The session shows up properly in both dead and connected mount/3, but only if I don’t use a custom :session_key in the protect from forgery plug.

plug :protect_from_forgery

Works. Session exists for both unconnected and connected mount/3.

plug :protect_from_forgery, session_key: "_phoenix_sa_csrf_token"

Breaks LV. I get all those messages in the logs saying to setup my session properly with csrf stuff.

I think because LV is hard coded to use "_csrf_token" as the session key. From the LV source code:

  defp load_csrf_token(endpoint, socket_session) do
    if token = socket_session["_csrf_token"] do
      state = Plug.CSRFProtection.dump_state_from_session(token)
      secret_key_base = endpoint.config(:secret_key_base)
      Plug.CSRFProtection.load_state(secret_key_base, state)
    end
  end

I think Endpoint.socket/3 needs to take an option to specify the session key for the csrf token…

# Router
plug :protect_from_forgery, session_key: "_phoenix_sa_csrf_token"

# Endpoint
socket "/live", Phoenix.LiveView.Socket, websocket: [
    connect_info: [
      session: [
        store: MySessionStore, key: "_my_app_session"
      ],
      csrf_session_key: "_phoenix_sa_csrf_token"
    ]
  ]

Something like that.