Is Rails' protect_from_forgery really useful? - ruby-on-rails

I'm asking this because I feel that it's making my life overly complicated when I start communicating with rails using ajax or flash.
I know it's nice to protect against CSRF, but couldn't I just check the referer or something instead?

Many users deactivate their referer, mostly not by choice.
But because they're behind a firewall that's blocking it.
Using protect from forgery is the only solution to protect you against CSRF.
But you can deactivate for any action you wish.
In your controller, you add :
skip_before_filter :verify_authenticity_token, :only => :create
This will deactive the token verification for the create action in the controller where you've added the filter.

Related

Devise InvalidAuthenticityToken

I am trying to create an authentication system with devise. When I try to login with a post request, without ajax, it gives me the "ActionController::InvalidAuthenticityToken" Error.
I've seen that this is supposed to be a common bug with devise. I've seen some usual approaches to it, which don't work for me:
To include an csrf token on the html: It is already included in the login site
Include a hackish solution like this: skip_before_action :verify_authenticity_token, if: -> { controller_name.include? 'sessions' }
. Unfortunately this doesn't change a thing. In the original solution I've seen it suggested to include it into Users::SessionsController. I can change whatever I like in this controller or even delete the whole controller and it still works the same.
This is supposed to be a problem with protecting from forgery according to other sources, but I can literally remove it from the application controller and I still have the same error.
class ApplicationController < ActionController::Base
# protect_from_forgery with: :exception
end
I believe that Devise checks the token independently from the rest of my app. This would also explain why it doesn't work even though there is a token at the sign in form. I have no clue what to do about it though.

Is protect_against_forgery required in Rails?

I have been reading on Rails security for hours now and I am a bit puzzled about the CSRF mechanism. It is stated everywhere I look that in order to switch it on you need to use the protect_against_forgery function.
I am working in a big application (Rails3.2-4) and can't seem to find any use of it in the codebase. Still the CSRF mechanism seems to be on:
protect_against_forgery? # true
What's the official answer from Rails on the matter? Do we need to set it explicitly or is it automatically set?
Yes, forgery protection is on by default. Should be enabled somewhere in your ApplicationController. Possibly in form of before_filter :verify_authenticity_token or something like that.
In the application.html.erb , we have csrf_meta_tags that are used to prevent the forgery request, if you have removed that tags , then you will get Invalid token authenticity error.
It is enabled by default.

AJAX call log out my account

I have a Rails 3 app and I am using Warden for authentication.
It works fine but when I try to use AJAX(POST) access one of the controller the application log out my account and ask me to log in again.
This is because of the rails CSRF token validation. There are a few different ways to deal with this:
Hacky, dirty shortcut - just make the AJAX call use HTTP GET instead of POST. GET will not look for CSRF token by default
Another dirty shortcut - turn off CSRF validation for this particular action in your controller
protect_from_forgery :except => :create
Properly implement CSRF token with AJAX calls, there are many guides out there, for example this one or this one

RoR UI & WebService: working around protect_from_forgery

I would like to use my RoR application to handle both UI and ReSTful API requests, however
I'm running into problems because of the protect_from_forgery flag. I don't want the API user to have to store a cookie or have to pass an authenticity_token; and, I want to be able to use the same ReSTful queries for both the UI and the API. For example,
https://host.domain.com/user/show/1
https://host.domain.com/user/create
The application controller would need to check if an API call is being made and then
not call the protect_from_forgery flag. So something like:
skip_before_filter :verify_authenticity_token, :only => :api
But here :api is an action and I would need to map a new route. I don't think this would allow me to use the same controllers and actions as the UI.
So I'm confused and unsure how to approach this problem. Surely this is a common issue
that many others have had to solve. I appreciate any help that folks could provide.
Here's a yucky idea: skip the before filter, for all actions. Then add a new filter
def verify_authenticity_token_or_api
api? || verify_authenticity_token
end
In your api method, work out whether the request is an api request. Be careful to not allow people to bypass forgery protection by making requests that look a bit like api requests - you might want to do something like invalidate the user's session if there is something that looks like a api request.
Another approach is just to have dedicated endpoints and controllers for your apis. While the stuff rails gets you for free is appealing, sometimes the resources you want to expose don't correspond exactly to your models

If writing your own authentication, does authenticate() go in the application_controller?

I'd like to write my own authentication instead of using one of the plugins.
Should my authenticate method go in the application_controller?
My idea is to place it there and then in each of the controllers use a before_filter
before_filter :authenticate
So my authenticate method would just check if the user_id is present in the session. If it's not there, the user would be redirected to an error page. If it is there, they would be allowed to see whatever url they wanted to visit.
Does this sound right?
Well, that's one way to setup the restful_authentication plugin. So yes, your homebrew solution could use
before_filter :authenticate
as well.

Resources