Rails - How to add CSRF Protection to forms created in javascript?

37,527

Solution 1

If you have <%= csrf_meta_tag %> in your layout somewhere and that is accessible to you from the js, then you can access it using $('meta[name="csrf-token"]')

See http://eunikorn.blogspot.com/2011/07/working-with-backbonejs-in-harmony-with.html for an idea on how to hack in csrf support into each backbone request

Solution 2

Best way I solved this, inside the form:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

Update:

It looks like the form_authenticity_token is private for controllers in the newer rails versions.

If that's the case for you, what I suggest is: declare a variable in a controller like: @form_token = form_authenticity_token and use it in the view you are looking for.

Solution 3

You can prepend the csrf token to every form that uses 'post' or 'delete'. Here it is in coffeescript:

$ -> 
  for f in $("form")
    if f.method == 'post' or f.method == 'delete'
      $(f).prepend("<input type='hidden' name='authenticity_token' value='" + token + "'>")

Make sure you have <%= csrf_meta_tags %> in your layout. It should already be in the standard 'application' layout, but add it if you're using a different layout.

Solution 4

I have a form inside a Vue component in a Rails 6 app.

To my surprise, it was sufficient to include a hidden input with the name authenticity_token within the Vue template and on page load, Rails filled out the value with a CSRF protection token.

E.g.

<template>
  <div id="app">
    <form
      action="/submit"
      method="post"
      @submit.prevent="onSubmit"
    >
      <input
        type="hidden"
        name="authenticity_token"
        value=""
      >
      <!-- rest of form -->
    </form>
  </div>
</template>

Which gets rendered as:

<div id="app">
  <form action="/submit" method="post">
    <input type="hidden" name="authenticity_token" value="zl9PJiE...">
    ...
  </form>
</div>
Share:
37,527
CamelCamelCamel
Author by

CamelCamelCamel

Updated on September 05, 2020

Comments

  • CamelCamelCamel
    CamelCamelCamel over 3 years

    I'm using backbone.js and it works great. but the forms I'm creating as a javascript template lacks the rails csrf protection token. How do I add it to templates I'm creating in javascript?

  • Chris Pfohl
    Chris Pfohl over 11 years
    See gist.github.com/3482636 for another example of how this can be hacked in. I have no idea if it's the same.
  • Franklin Yu
    Franklin Yu over 7 years
    It works, but why? Isn't form_authenticity_token private in the controller?
  • juliangonzalez
    juliangonzalez over 7 years
    Where is token declared?
  • juliangonzalez
    juliangonzalez over 7 years
    This doesnt work for me Rails 4.2.2. I get: undefined local variable or method 'form_authenticity_token' for #<#<Class:0x007ff80b1d36d8>:0x007ff7eec39b58>
  • lucianosousa
    lucianosousa over 7 years
    Hey guys, looks like form_authenticity_token is private for controllers like Franklin said. What I saw as a suggestion was declare a variable in a controller @form_token = form_authenticity_token and use it in the view.
  • sameers
    sameers over 6 years
    What @suga_shane means by writing, "make sure you have <%= csrf_meta_tags %>", is that this Rails helper generates a token for you and inserts it in the HTML head. The token is the content attribute in the <meta> tag with name csrf-token.
  • Jared Menard
    Jared Menard over 6 years
    This works for me in rails 4.2.5. Note: this form was generated in ERB and not in JS.
  • Meekohi
    Meekohi over 5 years
    Specifically: $.ajax(data: {authenticity_token: $('meta[name="csrf-token"]').attr("content")})