Search code examples
ruby-on-railsdeviseember.jsjquery-file-upload

InvalidAuthenticityToken after using Jquery File Upload


I have a Rails 4.0 app with an Ember.js frontend. I'm using Ember-Auth in conjunction with Devise to handle authentication. For the most part, everything works. However, if I use Jquery File Upload, then all subsequent queries to the server result in an InvalidAuthenticityToken error. The file upload itself works perfectly, but if for instance I visit the Organizations index page afterwards, I'll get the error. If I reload the page, then the errors stop coming and everything works fine again until I perform another upload.

The uploader looks like this:

didInsertElement: ->
  $('#image_upload').fileupload
    url: "/images"
    formData: [{ name: 'auth_token', value: Whistlr.Auth.get('authToken') }]
    success: (response) =>
      @get('parentView').get('controller').set('image_token', response.token)

Even if I remove everything but the url, I get the InvalidAuthenticityToken afterwards. Any idea what's happening?


Solution

  • Following my suspicion that the session was getting reset, I tried passing the authenticity_token back the client side from the server. Surely enough, it was changing. So I manually placed the new authenticity_token in the headers. The code looks like this:

    def create
      image = Image.create(image_params)
      render json: {image: image, authenticity_token: form_authenticity_token}, status: 201
    end
    
    $('#image_upload').fileupload
      url: "/images"
      dataType: "json"
      formData: [{ name: 'auth_token', value: Whistlr.Auth.get('authToken') }]
      success: (response) =>
        @get('parentView').get('controller').set('image_token', response.image.token)
        $('meta[name="csrf-token"]').attr('content', response.authenticity_token)
    

    Note the last line of the javascript, which replaces the csrf-token. Thankfully, this works. As far as I can tell, it's also secure. (If you see a security flaw, please let me know!) But it still seems weird that this is necessary. Nowhere else in my app do I have to manually replace the csrf-token. Why is this happening here? Is it because the session is getting reset, and if so, why is that happening here but not elsewhere?