Psst. It would be super cool if you could try the new Phoenix Boilerplate

Try now →

Tutorial

View on Github

Phoenix LiveView and Invalid CSRF token

csrfformsliveviewphoenix

One issue that is common to run into is a CSRF error when posting some sort of form rendered with LiveView. The issue is that a LiveView component is mounted twice. First time when the component is rendered by the initial request. Then it has the correct CSRF token. Next time, when it connect to the socket, it get the wrong CSRF token. Or at least wrong in the sense that it doesnt match the one in the page header.

STEP 1

So, to fix this, you need to setup so that the LiveView connection so it uses the same session options. Open endpoint.ex and change to:

  @session_options [
    store: :cookie,
    key: "_tutorial_key",
    signing_salt: "4qBWyMiY"
  ]

socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]]

...

plug Plug.Session, @session_options

Now that I have hooked up my session to the LiveView socket connection, I can create a plug that assigns the correct CSRF-token to a session cookie on every page request. I need to create a plug with the content:

defmodule TutorialWeb.GenerateCSRF do
  import Plug.Conn, only: [put_session: 3]

  def init(_opts), do: nil

  def call(conn, _opts), do: put_session(conn, :csrf_token, Phoenix.Controller.get_csrf_token())
end

(Thanks for the tip)

And mount that plug in the router:

  pipeline :browser do
    ...
    plug :put_secure_browser_headers
    plug TutorialWeb.GenerateCSRF
  end

Then, in my LiveView component product_list_live.ex, I can extract it from the session argument like:

  def mount(%{"csrf_token" => csrf_token} = _session, socket) do
    assigns = [
      conn: socket,
      csrf_token: csrf_token
   ]

    {:ok, assign(socket, assigns)}
  end

And lastly, in my template, I can not use the csrf token:

<%= link "Delete", to: Routes.product_path(@conn, :delete, product), csrf_token: @csrf_token, method: :delete, data: [confirm: "Are you sure?"] %>

SUCCESS

Now you should be able to delete a product:


Related Tutorials

Published 14 Feb

Improving LiveView UX with Phoenix Channels - Tagging part 3

channelsformsliveviewphoenixtagging

In the previous tutorial I set up the tagging interface. It had however a small issue. If I added a tag, it didnt really refocus on the input so I n..

Published 13 Feb

Tagging interface with Phoenix LiveView and Tailwind - Tagging part 2

formsliveviewphoenixtaggingtailwindtypeahead

In the previous tutorial, I set up the the backend for being able to add tags to products. I have also written a tutorial about adding a LiveView an..