user2067888
user2067888

Reputation: 1175

Rails 4.1.8 : Authentication token won't validate

I am a newbee to Rails. I have

  <%= csrf_meta_tags %>
  <%= javascript_tag "var AUTH_TOKEN = '#{form_authenticity_token}';" if protect_against_forgery? %>

in my application.html.erb. I need to post a form via ajax and I have,

data: data + "&authenticity_token="+AUTH_TOKEN,

in my ajax method for data. I verified that both the tokens, i.e. post method header authentication token X-CSRF-Token and the one I send Auth_TOKEN are same. I still get Can't verify CSRF token authenticity error. I don't want to skip the security, I need a proper way to handle this. Any idea? Thanks in advance.

Form

 <h3 id="emailModalLabel">Tell Your Friends About Us</h3>
 <form class="form-horizontal col-sm-12 validate" name="emailForm" id="emailForm">
    <div class="form-group"><label>Your Name *</label><label class="error" for="your_name" generated="true"></label><input id="your_name" name="your_name" class="form-control required" placeholder="Your name" data-placement="top" data-trigger="manual" data-content="Must be at least 3 characters long, and must only contain letters." type="text"></div>
    <div class="form-group"><label>Your E-Mail *</label><input id="your_email" name="your_email" class="form-control required email" placeholder="[email protected] (so that your friend can reply to you)" data-placement="top" data-trigger="manual" data-content="Must be a valid e-mail address ([email protected])" type="email"></div>
    <div class="form-group"><label>Friend's Name *</label><input id="friend_name" name="friend_name" class="form-control required" placeholder="Your friend's name" data-placement="top" data-trigger="manual" data-content="Must be at least 3 characters long, and must only contain letters." type="text"></div>
    <div class="form-group"><label>Friend's E-Mail *</label><input id="friend_email" name="friend_email" class="form-control required email" placeholder="[email protected] (so that you can email them)" data-placement="top" data-trigger="manual" data-content="Must be a valid e-mail address ([email protected])" type="email"></div>
    <div class="form-group"><label>Message</label><textarea id="message" name="message" class="form-control" rows="5" placeholder="Your message here.." data-placement="top" data-trigger="manual"></textarea></div>
    <div class="form-group"><p class="help-block pull-left text-danger hide" id="form-error">&nbsp; The form is not valid. </p></div>
    <span class="pull-right"><button class="btn col-md-5 col-sm-5 col-xs-5" data-dismiss="modal" aria-hidden="true">Cancel</button><button id="emailSubmit" type="submit" class="btn btn-default pull-right col-md-5 col-sm-5 col-xs-5">Send It!</button></span>
</form>

Ajax POST

$("#emailForm").validate({
    rules:{
        your_name: {required: true},
        your_email: {required: true, email: true},
        friend_email: {required: true, email: true},
        friend_name: {required: true}
    },
    submitHandler: function(form) {
        $("#emailSubmit").prop("disabled", true);
        var data = $("form#emailForm").serialize();
        $.ajax({
            type: "POST",
            url: "/send",//process to mail
            data: data + "&authenticity_token="+AUTH_TOKEN,
            success: function(msg){
                if(msg['success']){
                    $(".successContainer").toggleClass( "hide", 1000, "easeOutSine" );
                    setTimeout("$('#emailModal').modal('hide')", 5000);
                }else{
                    $(".errorContainer").toggleClass( "hide", 1000, "easeOutSine" );
                }


            },
            error: function(){
                $(".errorContainer").toggleClass( "hide", 1000, "easeOutSine" );
            }
        });
    }

});

The data in ajax request is serialized so it is a string, and I am appending token to that string.

Upvotes: 0

Views: 144

Answers (1)

kurenn
kurenn

Reputation: 1055

The best solution in here would be to implement a form_tag built-in rails helper, like:

<%= form_tag '#', class: 'form-horizontal col-sm-12 validate', name: 'emailForm', id: 'emailForm' do %>
  <div class="form-group">
    <label>Your Name *</label>
    <label class="error" for="your_name" generated="true"></label>
    <%= text_field_tag "your_name", "", id: 'your_name', class: 'form-control required', placeholder: 'Your name', data: { placement: 'top', trigger: 'manual', content: 'Must be at least 3 characters long, and must only contain letters.' }%>
  </div>
  .
  .
  .
<% end %>

Notice I just included the first text_fiel_tag, you can include any other field tag by using Rails.

What's behind this? well Rails uses a token to prevent CSRF attacks.

For the ajax call you have to serialize the data from the form and then send it all along just as you are already doing it.

A good tip when working with Rails, try to always use built-in helpers, such as for the forms, images, links and so on.

Upvotes: 0

Related Questions