Paperclip gem triggering CSRF token verification problems

csrf, paperclip, ruby-on-rails-3, ruby-on-rails-3.1

Solution

I know that it's been a while since I first posted the above question, but people are still finding it in their searches, so I thought I'd update things with an answer.

The problem I discussed above had nothing to do with Paperclip. The form is being submitted without a csrf token because I am using remotipart.js to handle the submission of forms that have file attachments. Remotipart enables an ajax-like submission of a form by copying the form data into an i-frame, which then makes a normal (i.e., non-ajax) submission while your site stays active. See this article for a more detailed description of ajax file uploads via i-frame.

In previous versions of remotipart the csrf token was not copied over to the form being submitted by the i-frame. The good people supporting remotipart have now fixed this shortcoming. You can find the fix here

Problem

I have a Rails 3.1 app that makes use of the paperclip gem (v 3.4.0). In a nutshell. I have a story model and a post model. A story can have many posts. ``` #story.rb class Story < ActiveRecord::Base attr_accessible :title, :user_id, :username, :posts_attributes belongs_to :user has_many :posts, :dependent => :destroy, :order => "created_at DESC" accepts_nested_attributes_for :posts, :reject_if => lambda { |t| t['contents'].nil? } end ``` ``` #post.rb class Post < ActiveRecord::Base attr_accessible :contents, :photo, :dimensions belongs_to :story, :touch => true belongs_to :user, :touch => true has_attached_file :photo, :styles => { :medium => { :geometry => "400x400>" }, :thumb => { :geometry => "100x100>" }, }, :processors => [:thumbnail], :storage => :s3, :s3_credentials => "#{Rails.root.to_s}/config/s3.yml", :path => "/:style/:id/:filename" before_save :extract_dimensions serialize :dimensions validates :contents, :presence => true, :length => { :maximum => 399, :minimum => 5 } validates :user_id, :presence => true validates_attachment_content_type :photo, :content_type => ['image/jpeg', 'image/png', 'image/gif', 'image/jpg'], :message => "Sorry, we don't support that type of image format" end ``` As you can see, posts may have a photo attachment. I use paperclip to manage these attachments. I generate the form that POSTs these posts dynamically on the client with javascript/jquery. My problem is this . . . If the post does NOT include a photo attachment everything works perfectly. IF, HOWEVER, A POST HAS A PHOTO ATTACHMENT, I receive the following error message and the post doesn't POST: ``` WARNING: Can't verify CSRF token authenticity User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 61 LIMIT 1 (0.3ms) BEGIN (0.2ms) COMMIT Completed 401 Unauthorized in 238ms ``` As a result, my session data is destroyed, and I can't even see the request headers with Firebug. The put request simply does not appear in firebug. Now, not surprisingly, I can get around this problem with the following in the PostController: ``` skip_before_filter :verify_authenticity_token, :only => [:create] ``` But I don't want to give up this security. I have also tried adding the CSRF header to my form via js/jquery: ``` jQuery.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf- token"]').attr('content')); } }); ``` But that doesn't solve the problem, and as I said above, I can't even see the request header data to see the header. Can anyone come-up with a reason why paperclip triggers the problem?

Original source