2

I apply the CSRF in Controller by adding this:

  class ApplicationController < ActionController::Base
     protect_from_forgery
  end

and I do a post request to my API using Postman. The funny result is I can't verify CSRF, but the data I send still be inserted into DB.

Here is the server log.

 Processing by Api::ListingsController
   Parameters: {"listing"=>{...}}
 Can't verify CSRF token authenticity
   (0.2ms)  BEGIN
 SQL (0.6ms)  INSERT INTO "listings" ...
   (0.4ms)  COMMIT
 Completed 201 Created in 54ms (Views: 0.2ms | ActiveRecord: 6.3ms)

Seems everything is fine, and data is in DB now! Why is CSRF not working?

Anyone can give any explains?

Lahiru Jayaratne
  • 1,684
  • 4
  • 31
  • 35
Eason Caizhen Liu
  • 459
  • 1
  • 5
  • 12

2 Answers2

3

There are 3 behaviours that a csrf token mismatch can trigger:

  • raise an exception (:exception)
  • reset the session to a new, empty session (:reset_session)
  • use an empty session for the request, but don't reset it completely (:null_session)

The rationale for the last 2 is that the point of a CSRF attack is usually to abuse the fact that the user is already logged in and thus the browser will send session cookies with the request. Therefore reseting or ignoring the session (assuming that is where credentials are stored) will make the request proceed as an unauthenticated request.

If the application doesn't require the user to be logged in then :null_session and :reset_session will allow the request to proceed.

The default behaviour has changed over the years, but as of rails 4.2 is is :null_session. You can change it by specifying a with option to protect_from_forgery

Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174
  • Thx man! I added 'protect_from_forgery with: :null_session' in 'ApplicationController', but the problem is still there. Can't verify CSRF token authenticity but data still insert into database. – Eason Caizhen Liu Oct 31 '15 at 13:12
  • That's what I was explaining - null session just clears out the session. If you want an exception to be raised, use :exception – Frederick Cheung Oct 31 '15 at 13:19
0

In ApplicationController you can add

class ApplicationController < ActionController::Base
    protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format      == 'application/json' }
    # Or
    # skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'application/json' }
end
Vincent Nguyen
  • 311
  • 3
  • 5
  • None of this works in my case. I have am app based on Michael Hartl user authorization. It is based on Rails 4.2.5 and worked until morning when I executed a bundle update. After that no log in, log out, etc. Sessions are not created. Previous bundle update executed was 2 days ago. App worked at that time. I have an API build on top of this app which is working. Only the main app died. Can't make it work again. The main app is sending the wrong token for verification instead the correct one stored in the users table. Don't know what generated this wrong token. – L.D Nov 20 '15 at 19:40