Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Auth Token and Ajax

Okay so from what I've read on other websites and on stack overflow, Rails throws this Authentication token error because my form doesn't pass the token -- and it's a security feature. This I understand.

However I don't really have a form. I have ajax here -- my javascript posts the id'ed information into a processing function.

So my question is, how do I get the authentication token to my controller?

My view looks like this:

<% for transaction in @transactions %>
        <% if transaction["category"] == '' %>
        <% transaction["category"] = "Uncategorized" %>
                        <% end %>

                        <tr title = "<% if params[:type] %><%= params[:type] %><% else %>Purchases<% end %> <%= transaction["id"] %>" >

                            <td class="check"><a class="help" href="#"><img src="/images/icons/help.png" alt="?" /></a><input type="checkbox" /></td>
                            <td class="date"><% if transaction["date"] != "0000-00-00 00:00:00" %><%= transaction["date"].to_date.strftime("%B %d") %><% end %></td>

                            <% if params[:type] == "Bills" || params[:type] == "Reimbursements" %>
                            <td class="payee"><%= transaction["payee"] %></td>
                            <td class="details"><%= transaction["details"] %></td>
                            <% else %>
                            <td class="description"><% if transaction["detail"] == "undefined" %>n/a<% else %><%= transaction["detail"] %><% end %></td>
                            <td class="category">n/a</td>
                            <% end %>

                            <td class="amount">-$<%= transaction["amount"] %></td>
                        </tr>

                    <% end %>

The corresponding ajax is as follows:

/* send ids by ajax */
$('#tableActions li a').click(function() { 
    if(!$(this).hasClass('disabled')) {
        action = $(this).text();
        ids = new Array();
        i = 0;
        $('td.check input','#tableHolder').each(function() { if($(this).attr('checked')) { ids[i++] = $(this).parents('tr').attr('title'); } });
        $.ajax({
            type: "POST",
            url: "/bulkaction",
            data: "=" + action + "&ids=" + ids + "&authenticity_token=" + encodeURIComponent(AUTH_TOKEN),
            success: function(data){
                $('#tableHolder').html(data);
                /* bring back all functionality */
                initTable();
                /* set default sorting by date desc */
                $('th').removeClass('sortUp sortDown');
                $('th:eq(1)').addClass('sortDown'); 
                /* disable all actions */
                $('#tableActions li a').addClass('disabled');

            }
        });
    }
    return false;
});

My processing logic in the controller looks like

    def bulkaction
            if request.post?
                ids = params[:ids]
                #Need to create a function here to parse out my string
                puts ids #for testing purposes, just put my ids onto the console
            end

puts "This function was accessed and ran."
end

And finally the console says

Processing UserController#bulkaction (for ::ffff:xx.xxx.xxx.xxx at 2009-07-06 23                                                                             :29:49) [POST]
  Parameters: {"ids"=>"Purchases 10040963"}

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticit                                                                             yToken):
  /usr/local/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
  /usr/local/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
  /usr/local/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
  /usr/local/lib/ruby/1.8/webrick/server.rb:162:in `start'
  /usr/local/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
  /usr/local/lib/ruby/1.8/webrick/server.rb:95:in `start'
  /usr/local/lib/ruby/1.8/webrick/server.rb:92:in `each'
  /usr/local/lib/ruby/1.8/webrick/server.rb:92:in `start'
  /usr/local/lib/ruby/1.8/webrick/server.rb:23:in `start'
  /usr/local/lib/ruby/1.8/webrick/server.rb:82:in `start'

It would be very helpful if someone were able to tell me where I was going wrong.

like image 920
Sam Avatar asked Jul 07 '09 03:07

Sam


3 Answers

Solved! changed the ajax to

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

And I added to the head for each page

<%= javascript_tag "const AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>
like image 135
Sam Avatar answered Oct 30 '22 02:10

Sam


This technique works well if you are using jQuery.

http://henrik.nyh.se/2008/05/rails-authenticity-token-with-jquery

like image 36
pantulis Avatar answered Oct 30 '22 02:10

pantulis


The site henrik.nyh.se seems to be down. The version there also contains an error which turns the get request into a post request with Internet Explorer. This fixed version is from: http://www.justinball.com/2009/07/08/jquery-ajax-get-in-firefox-post-in-internet-explorer/

jQuery(document).ajaxSend(function(event, request, settings) {
  if (typeof(AUTH_TOKEN) == "undefined") return;
  if (settings.type == 'GET') return; // Don't add anything to a get request let IE turn it into a POST.
  settings.data = settings.data || "";
  settings.data += (settings.data ? "&" : "") + "authenticity_token=" + encodeURIComponent(AUTH_TOKEN);
});
like image 24
Rainer Blessing Avatar answered Oct 30 '22 00:10

Rainer Blessing