I was using authlogic on my Rails app and decided to remove it in favor of implementing 3rd party authentication using OAuth. Switching to to this approach has left me with a very interesting problem:
The rails session object is empty when I make a post request from the app. A 'get' request always has the session populated but not a post. I can verify that it is indeed posting the session cookie in both cases but dont see why this is happening.
Any ideas why this is happening or tips to debug this?
This is because the posts were missing the csrf token. For some reason, Authlogic takes care of the CSRF verification for AJAX posts.
Related
I have a fully working product on Rails 5. I now wish to make a Chrome extension, using which users can create an 'Article'.
However, requests from my Chrome extension will be treated as Cross Site by my rails app. Hence, I was thinking of not doing the CSRF check at all on just my create action.
What is the biggest security risk associated with this? I understand after this, anyone will be able to make POST request to my server that creates a new article - however, this is not a damaging action like update, or worse, delete.
The Rails guide states that,
CSRF attack method works by including malicious code or a link in a
page that accesses a web application that the user is believed to have
authenticated. If the session for that web application has not timed
out, an attacker may execute unauthorized commands.
If a CSRF token is a valid one, it is a kind of assurance that the user session has not been hijacked and the request has been made with the user consent.
For more info, I recommend you to refer the Rails guide http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf
So I am trying to understand what to do here... I am doing a POST call to my Django server from iOS and I keep getting the 403 Error (Invalid CSRF Token). I am thinking about implementing a function that will return me the token (you will need to be logged in to access that function), and then add the token to my POST call.
Now... I don't understand what is the point of doing that? If I use TastyPie and the required login is APIKey... should I just exempt the csrf check?
To make sure I understand things right... is the CSRF generated per user session? Therefore, if I don't use Cookies, CSRF is not necessary?
How do people usually use their Django Servers with an iOS and making such POST calls?
Thanks!
You're right: if you don't use cookies to manage your sessions, you don't need CSRF protection. CSRF works because session cookies are automatically attached to the request; access tokens are not.
I personally found this article very useful. It is definitely worth reading, and would probably answer a lot of your questions.
As for tastypie: it allows SessionAuthentication. If you allow session authentication in tastypie, I suggest you look into a way to protect your users against CSRF. For other authentication schemes this doesn't seem necessary. As far as I know, Dmitry is right about tastypie disabling CSRF by default, which means it is strange that you get that 403 Error. Perhaps there is something else going on. Try wrapping the view in #csrf_exempt.
As for CSRF tokens, they are also called session independent nonces. They are meant to be permanent, but you probably know that is impossible for cookies. Anyway, this means that CSRF cookies persist through sessions.
You're right, CSRF does not make much sense in this case, because its purpose is to protect users from data tampering in a browser.
I believe that Tastypie disables CSRF on its views by default.
What is the best way to make authentication?
on frontend I use Angular.js
on backend: Ruby on Rails
Rails app using as API for my frontend.
UPDATE:
This is will be single page application.
Frontend wiil be developed in Angular.js, backend in Ruby on Rails.
In ideal I want to build backend as collection of resources returned in json.
I search best method of security implementation.
When user open the app I need to check if user authenticated.
If not - go to login page,
If authenticated - open that he wants and return needed resource from backend.
I think that I need to store auth token on the client side.
What is the best method to generate it, or maybe Rails already generate it for me?
I don't know Angular.JS at all but I will try to provide you general information on rails that you can use with any Javascript Framework.
For authentication, you just needs:
A model for users
a controller which handle login, this method check user login/password, create a session object with all information needed (session is stored on server side and a cookie is used on client-side to associate each request to a session)
A controller for handling logout which basically only destroy the user's session
You have a good implementation in the rails tutorial here, or you can find several plugins (authlogic seems to be the recommendation of stackoverflow usershere).
Then, there is few differences between handling authentication with static html pages or with AJAX:
A HTML request will send login and password to the controller, which will automatically redirect it to another internal page once the session create
In AJAX, the javascript on client side should send an ajax request, look for the answer by the server (success / failure) and launch adapted actions (message if failure, redirection if success)
In both cases, the important thing is to check that the user is authenticated at at each controller otherwise anybody would be allowed to launch action or access internal information.
I'm trying to do something similar and I found this example app which has been very useful to get me going in the right direction: https://github.com/karlfreeman/angular-devise
Also checkout further discussion about it here: https://github.com/karlfreeman/angular-devise/issues/1
And here's another repo which takes a slightly different approach: https://github.com/colindensem/demo-rails-angularjs
I ended up borrowing ideas from all of the above. Here's a working demo if anyone's interested: https://github.com/jesalg/RADD
I have a backbone app which is being fed data by a Rails backend.
When trying to call create from Backbone collection, the session in rails gets destroyed.
Any pointers on how to overcome it?
This sort of thing is almost always a result of a bad or non-existent CSRF token. In recent versions of Rails 3.0.4+, any request that doesn't have a CSRF token that matches the token generated for the users current session will destroy the session as a security measure.
Here is some more info on CSRF security in Rails:
http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf
You can easily test to see if this is what is causing your problem by commenting out the protect_from_forgery method call (probably in your application_controller.rb file). But I wouldn't recommend disabling it permanently for security reasons.
I use Rails request_forgery_protection mechanism to protect my POST actions from CSRF attacks and captcha to protect the GET actions. This way if someone stages a two-phase attack within one session, GET-ting the form with the current token and then POST-ing a forged request with that token, he will eventually be faced with a captcha check.
I'm stuck with that though, because Rails doesn't regenerate the CSRF token until the end of session. That doesn't seem right to me, I'd think the token should be renewed before the next action. I'm wondering maybe I have tweaked something wrong? Is there another way of doing this?
Thanks.
I've not sure if this is a good idea or not, but you can nil out the token yourself on get requests from inside your application controller.
before_filter :reset_csrf
private
def reset_csrf
session[:_csrf_token] = nil if request.get?
end
In case form token is NOT regenerated for each page request, this protection is bad. I faced it sometime ago (when testing Redmine, which is RoR-based) and reported this issue, but didn't retested it.
If it's still not regenerated, I suggest you report this to RoR team.