This solution is flawed and insecure. After giving the problem some thought, I came up with something more suitable for production:
Define a helper function for Liveviews.
defmodule MyAppWeb.LiveViewUtils do
use MyAppWeb, :verified_routes
import Phoenix.LiveView
def push_cookie(socket, key, value) do
push_event(socket, "fetch-cookies", %{
method: "PUT",
path: ~p"/cookies",
token: Phoenix.Token.sign(socket, "cookie", {key, value})
})
end
end
Catch this event on the client side in assets/js/app.js and send a fetch request back to the server (to a regular controller).
window.addEventListener("phx:fetch-cookies", ({ detail }) => {
const { path, method, token } = detail;
fetch(path, {
method,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token }),
});
});
Add a route for this request:
put "/cookies", MyAppWeb.CookiesController, :put
Define a controller.
defmodule MyAppWeb.CookiesController do
use MyAppWeb, :controller
def put(conn, %{"token" => token}) do
case Phoenix.Token.verify(conn, "cookie", token, max_age: 60) do
{:ok, {key, value}} ->
conn
|> fetch_session()
|> put_session(key, value)
|> send_resp(:ok, "")
_ ->
send_resp(conn, :unauthorized, "")
end
end
end
The approach above can be easily extended to accommodate the push_delete_cookie/2 functionality.






















