Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct use of protect_from_forgery in Rails app serving Web and API

I am developing a Rails 4 app that serves a mobile app through an API, and has a web UI for admins to manage the application. There's also a couple of web pages that users will see (successful e-mail confirmation and reset password).

I created two sets of controllers: one set inherits from APIController, and the other from AdminController. Both of these inherit from ApplicationController. The remaining controller responsible for user facing web pages also inherits from ApplicationController.

Given this scheme, I am unsure on how to properly implement CSRF protection with protect_from_forgery. I currently have the following:

class ApplicationController < ActionController::Base
  # ...
end

module API
  class APIController < ApplicationController
    protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
    # ...
  end
end

module Admin
  class AdminController < ApplicationController
    protect_from_forgery with: :exception
    # ...
  end
end

class UsersController < ApplicationController
  protect_from_forgery with: :exception
  # ...
end

So my question is: is this correct? Is there any way to improve it? Is the check in the APIController pointless since all API requests will be only JSON anyway?

Brakeman complained that there is no protect_from_forgery call in ApplicationController, but maybe it doesn't see the calls in the subclasses.

Thanks in advance!

like image 624
Roma149 Avatar asked Dec 10 '15 00:12

Roma149


1 Answers

You can see here, on their (brakeman) Github page that it checks for the presence on the ApplicationController only

Your Admin and Users controllers are fine with the protect_from_forgery with: :exception

The default behaviour on Rails 4 for protect_from_forgery is :null_session, you could remove the option with: if you want.

About improving, I would implement a way to save a token in the user and match for every request, that way the user requesting the API would have to send his token every request. Doing this you avoid the necessity in getting the CSRF token and then send the request with this token. For mobile users for example, this is one extra request where you could solve just by saving the right token. If someone get this token though, it could pass as the user and change the data. But you can look for more ways on how to make this more secure.

The CSRF can happen if you save the token in sessions or cookies, you would have to take care of that independently, in case you choose to save like that.

If you intend to use the API for mobiles, save the token(in the strategy I said first) on the mobile(memory or local db) and it will be more safe.

like image 163
Cassio Cabral Avatar answered Oct 09 '22 01:10

Cassio Cabral