I have a LiveView that lists Students at /students. I also have a resources "/students" that handles all the rest of my CRUD operations for students. When I try to DELETE to /students/:id using the link on the page, I’m getting an invalid CSRF token error:
[debug] ** (Plug.CSRFProtection.InvalidCSRFTokenError) invalid CSRF (Cross Site Request Forgery) token, make sure all requests include a valid '_csrf_token' param or 'x-csrf-token' header
My delete button looks like this:
<span><%= link "Delete", to: Routes.student_path(@socket, :delete, student), method: :delete, data: [confirm: "Are you sure?"] %></span>
If you are using a form to do the delete then you can add the CSRF token as a hidden field something like this.
# In a controller etc., you can use an assign and add the token
def index(conn, _) do
render conn, "index.html", token: get_csrf_token()
end
# In a view add the token as a hidden field using the assign
<form>
...
<input type="hidden" value="<%= @token %>" name="_csrf_token"/>
...
</form>
# Or call the get_csrf_token() function directly in the template
<form ...
...
<input type="hidden" value="<%= Phoenix.Controller.get_csrf_token() %>" name="_csrf_token"/>
...
</form>
I fixed this by adding a _csrf_token parameter to the data list. I’m not sure why data-csrf works for regular requests and not requests coming from a LiveView, however.
Hmm, it seems that I was mistaken. I had made a typo and added _csrf_token outside of the data list. This caused some bug with LiveView, which caused that attribute to not be updated when LiveView picked up from where the GET request left off. That meant that I had a dangling -csrf-token attribute which was used instead of the data-csrf attribute (which was updated via LiveView to some new CSRF token – I checked using the inspect tool that these attributes were indeed different).
Basically what this means is, LiveView is updating the CSRF token to something that is invalid. An explanation from @chrismccord or @josevalim would be appreciated here.