Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override the protect_from_forgery strategy in a controller

I want to build a rails app with two different protect_from_forgery strategies: one for the web application, and one for the API.

In my application controller I have this line of code: protect_from_forgery with: :exception in order to prevent CSRF attacks, it works just fine.

In my API namespace, I created an api_controller that inherits from my application controller, and that is the parent class of all the other controllers in the API namespace, and I changed the code above with: protect_from_forgery with: :null_session.

Sadly, I have an error when trying to make POST request: "Can't verify CSRF token authenticity".

I don't want to skip the verify_authenticity_token method in my API controllers, I just want to have two distinct strategies in my app, so how do I override the protect_from_forgery strategy defined in my application controller ?

Edit: Ok, so I eventually did what I did not want to do in the first place: change the inheritance of my api_controller: it now inherits from ActionController::Base, and no longer from my application controller. It does work now but:

  1. It does not answer my question i.e. overriding the protect_from_forgery strategy.
  2. It is not DRY as I have to copy/past what was previously in my application_controller.

So if anyone has a real way to overwrite this method, I'd appreciate it.

like image 638
HHK Avatar asked May 15 '14 08:05

HHK


3 Answers

What if you leave the protect_from_forgery with: :exception in the application controller but then you put the following in your API controller?

skip_before_action :protect_from_forgery
protect_from_forgery with: :null_session

That way, you still get the standard CSRF attack protection for all controllers in your web application but you also get the null session behavior for your API methods.

like image 105
Bart Avatar answered Oct 15 '22 18:10

Bart


I am running an application with a similar structure - Web App + API. I solved the CSRF problem like this:

  • Apply protect_from_forgery only for non API requests
  • My API endpoint is api.example.com, so I used subdomain constraint to distinguish API and web app requests

Code:

class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception, if: :isWebRequest?

  def isWebRequest?
    request.subdomains[-1] != 'api'
  end

end
like image 6
Lenin Raj Rajasekaran Avatar answered Oct 15 '22 18:10

Lenin Raj Rajasekaran


Late to the party, but something like this can be done:

class YourCustomStrategy
  def initialize(controller)
  end

  def handle_request
  end
end

And in your ApplicationController or where you want:

class ApplicationController < ActionController::Base
 protect_from_forgery with: YourCustomStrategy
end
like image 1
MatayoshiMariano Avatar answered Oct 15 '22 17:10

MatayoshiMariano