title: WARNING: Can't verify CSRF token authenticity
body: <p>I'm having trouble making a cross-domain request from my shopify site to my rails app, which is installed as a shopify app. The problem, as stated in the title, is that my server warns me that it <code>Can't verify CSRF token authenticity</code> I'm making the request from a form returned by my rails app, which includes the relevant CSRF token. The request is done with jQuery's ajax method, and the preflight OPTIONS request is being handled by <a href="https://github.com/cyu/rack-cors" rel="nofollow noreferrer">rack-cors</a>.</p>
  
  <p>I've included the X-CSRF-Token in my headers as was suggested in <a href="https://stackoverflow.com/questions/7203304/warning-cant-verify-csrf-token-authenticity-rails">this answer</a>. My post request is being made from a form, so my question is not answered <a href="https://stackoverflow.com/questions/14039475/rails-3-cant-verify-csrf-token-authenticity">here</a>. The options request (mentioned in <a href="https://stackoverflow.com/questions/13043444/warning-cant-verify-csrf-token-authenticity-error-cors-with-devise-and-to">this question</a>) is indeed being handled, as I just confirmed by asking <a href="https://stackoverflow.com/questions/14226388/should-the-cors-preflight-options-request-return-200-ok">this question</a>. I've been stuck on this for a while, and have done a bit of reading.</p>
  
  <p>I'm going to try walking through the process code-snippet by code-snippet, and maybe by the time I finish writing this post I will have discovered the answer to my problem (if that happens, then you won't ever get a chance to read this paragraph).</p>
  
  <p>Here are the new and create methods from my controller.</p>
  
  <pre><code>class AustraliaPostApiConnectionsController &lt; ApplicationController
  
    # GET /australia_post_api_connections/new
    # GET /australia_post_api_connections/new.json
    def new
      # initializing variables
  
      respond_to do |format|
        puts "---------------About to format--------------------"
        format.html { render layout: false } # new.html.erb 
        format.json { render json: @australia_post_api_connection }
      end
    end
  
    # POST /australia_post_api_connections
    # POST /australia_post_api_connections.json
    def create
  
      @australia_post_api_connection = AustraliaPostApiConnection.new(params[:australia_post_api_connection])
  
      respond_to do |format|
        if @australia_post_api_connection.save
  
          format.js { render layout: false }
        else
  
          format.js { render layout: false }
        end
      end
    end
  end
  </code></pre>
  
  <p>(I wonder about the respond_to block in the create method, but I don't think that would cause the CSRF token to fail verification.)</p>
  
  <p>Within my app, at /AUSController/index, I have an ajaxified GET request that brings back the form from /AUSController/new. My goal is to be able to make all the same calls from a cross-domain origin as I can from within my app. Right now the GET request works for both, and so I will neglect to include the 'new' form. When the HTML is finally rendered, the form element has the following:</p>
  
  <pre><code>&lt;form method="post" id="new_australia_post_api_connection" data-remote="true" class="new_australia_post_api_connection" action="http://localhost:3000/australia_post_api_connections" accept-charset="UTF-8"&gt;
  
  &lt;!-- a bunch more fields here --&gt;
  
      &lt;div class="field hidden"&gt;
        &lt;input type="hidden" value="the_csrf_token" name="authenticity_token" id="tokentag"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>The CSRF token is generated by a call to <code>form_authenticity_token</code> as detailed in one of the references <a href="https://stackoverflow.com/questions/7203304/warning-cant-verify-csrf-token-authenticity-rails">mentioned above</a>.</p>
  
  <p>The next step is done differently in the two cases: </p>
  
  <p>My app successfully returns the new form to the shop upon an ajax request. I've tested this within the app, that is by making an ajax call to /controller/new from /controller/index, and then submitting the form. This works like a charm. The js that is returned from a successful POST within my app is as follows:</p>
  
  <pre><code>/ this is rendered when someone hits "calculate" and whenever the country select changes
  :plain
    $("#shipping-prices").html("#{escape_javascript(render(:partial =&gt; 'calculations', :object =&gt; @australia_post_api_connection))}")
  </code></pre>
  
  <p>Which renders the following partial,</p>
  
  <pre><code>= form_tag "/shipping_calculations", :method =&gt; "get" do
  
    = label_tag :shipping_type
    %br
    - @service_list.each_with_index do |service, index|
      - checked = true if index == 0
      = radio_button_tag(:shipping_type, service[:code], checked)
      = label_tag(:"shipping_type_#{service[:code]}", service[:name])
      = " -- $#{service[:price]}"
      %br
  </code></pre>
  
  <p>When I call it from the same domain, <code>request.header</code> contains the following:</p>
  
  <pre><code>HTTP_X_CSRF_TOKEN
  the_token_I_expect=
  
  rack.session
  {
    "session_id"=&gt;"db90f199f65554c70a6922d3bd2b7e61", 
    "return_to"=&gt;"/", 
    "_csrf_token"=&gt;"the_token_I_expect=", 
    "shopify"=&gt;#&lt;ShopifyAPI::Session:0x000000063083c8 @url="some-shop.myshopify.com", @token="some_token"&gt;
  }
  </code></pre>
  
  <p>And the HTML is rendered and displayed nicely.</p>
  
  <p>From the cross domain source, however, things are understandibly more complicated. This is where CORS and CSRF tokens and routes and all these little details start creeping in. In particular, when I make the ajax call I use the following script (which does not live in my rails app, it lives on the cross-domain server). The action of this ajax request is attached to the submit button by the callback function from the GET request, and I've included the GET request for the sake of completion.</p>
  
  <pre><code>&lt;script&gt;
  
    var host = "http://localhost:3000/"
    var action = "australia_post_api_connections"
  
    console.log("start")
    $.ajax({
      url: host + action,
      type: "GET",
      data: { weight: 20 },
      crossDomain: true,
      xhrFields: {
        withCredentials: true
      },
      success: function(data) {
        console.log("success");
        $('#shipping-calculator').html(data);
  
        $('#new_australia_post_api_connection')
        .attr("action", host + action);
  
      $('.error').hide();
  
      $(".actions &gt; input").click(function() {
        console.log("click")
        // validate and process form here
        $('.error').hide();
  
        var to_postcode = $("input#australia_post_api_connection_to_postcode").val();
  
        // client side validation
        if (to_postcode === "") {
          $("#postcode &gt; .error").show();
          $("input#australia_post_api_connection_to_postcode").focus();
          return false;
        }
  
        tokentag = $('#tokentag').val()
  
        var dataHash = {
          to_postcode: to_postcode,
          authenticity_token: tokentag // included based on an SO answer
        }
  
        // included based on an SO answer
        $.ajaxSetup({
          beforeSend: function(xhr) {
            xhr.setRequestHeader('X-CSRF-TOKEN', tokentag);
          }
        });
  
        $.ajax({
          type: "POST",
          url: host + action,
          data: dataHash,
          success: function(data) {
            $('#shipping-prices').html(data);
          }
        }).fail(function() { console.log("fail") })
          .always(function() { console.log("always") })
          .complete(function() { console.log("complete") });
        return false;
  
      });
  
      }
    }).fail(function() { console.log("fail") })
    .always(function() { console.log("always") })
    .complete(function() { console.log("complete") });
  
    $(function() {
    });
  
  &lt;/script&gt;
  </code></pre>
  
  <p>However, when I call it from this remote location (the distant slopes of Shopify), I find the following in my request headers,</p>
  
  <pre><code>HTTP_X_CSRF_TOKEN
  the_token_I_expect=
  
  rack.session
  { }
  </code></pre>
  
  <p>And I receive a very unpleasant <code>NetworkError: 500 Internal Server Error</code> rather than the <code>200 OK!</code> that I would like... On the server side we find the logs complaining that,</p>
  
  <pre><code>Started POST "/australia_post_api_connections" for 127.0.0.1 at 2013-01-08 19:20:25 -0800
  Processing by AustraliaPostApiConnectionsController#create as */*
    Parameters: {"weight"=&gt;"20", "to_postcode"=&gt;"3000", "from_postcode"=&gt;"3000", "country_code"=&gt;"AUS", "height"=&gt;"16", "width"=&gt;"16", "length"=&gt;"16", "authenticity_token"=&gt;"the_token_I_expect="}
  WARNING: Can't verify CSRF token authenticity
  Completed 500 Internal Server Error in 6350ms
  
  AustraliaPostApiConnection::InvalidError (["From postcode can't be blank", "The following errors were returned by the Australia Post API", "Please enter Country code.", "Length can't be blank", "Length is not a number", "Height can't be blank", "Height is not a number", "Width can't be blank", "Width is not a number", "Weight can't be blank", "Weight is not a number"]):
    app/models/australia_post_api_connection.rb:78:in `save'
  </code></pre>
  
  <p>The lack of a <code>rack.session</code> seems suspicious like the cause of my misery... but I haven't been able to find a satisfying answer.</p>
  
  <p>Finally I have seen fit to include my rack-cors setup, in case it is useful.</p>
  
  <pre><code># configuration for allowing some servers to access the aus api connection
  config.middleware.use Rack::Cors do
    allow do
      origins 'some-shop.myshopify.com'
      resource '/australia_post_api_connections',
        :headers =&gt; ['Origin', 'Accept', 'Content-Type', 'X-CSRF-Token'],
        :methods =&gt; [:get, :post]
    end
  end
  </code></pre>
  
  <p>Thank you so much for even reading all of this. I hope the answer has to do with that empty <code>rack.session</code>. That would be satisfying, at least.</p>