Tutorial

Phoenix LiveView and Invalid CSRF token

This post was updated 01 May - 2020

phoenix csrf forms liveview

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 doesn't 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.Live.View.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
<small>([Thanks for the tip](https://github.com/phoenixframework/phoenix_live_view/issues/111#issuecomment-547251854))</small>

And mount that plug in the router:

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

Then, in my LiveView component productlistlive.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 - 2020
Updated 01 May - 2020

Improving LiveView UX with Phoenix Channels - Tagging part 3

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 - 2020
Updated 01 May - 2020

Tagging interface with Phoenix LiveView and Tailwind - Tagging part 2

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