Rails 3 : Can't verify CSRF token authenticity - ruby-on-rails

When i tried to post data through my REST Client ,i am getting a warning like this
Warning :Can't verify CSRF token authenticity.
How to solve this.

I believe you are trying to make a POST from a link. By default links aren't supposed to make POST requests, only GET ones. So when you try to make the connection to your server, Rails warns you about this.
One way to bypass this kind of behavior is, instead of using a link, use a form. So you can make proper POST requests to the server.
Alternatively, you can remove the protect_from_forgery line from your application_controller, so Rails doesn't do this kind of verification, but this is extremely not recommended.

You could do this, (but not recommended :)), skip forgery protection
Ex: you are posting data to PostController => Create action
class PostsController < ApplicationController
before_filter :protect_from_forgery, :except => [:create]
def create
#your method
end
end
but having said that, I'm sure there should be a better way to do what you want to do, so if you could explain what you want to do, someone could help
HTH

nop
I missed the following line in my application.js
//= require jquery_ujs
I replaced it and its working..

Related

In Ruby on Rails, how to intercept the Devise gem's email sending functionality and change it to call an API instead? [duplicate]

As my reputation is lower than 50, so Im not able to comment below the accepted answer in this post In Rails Devise gem how to modify the send_reset_password_instructions method? for more information.
I want to customize recoverable.rb in devise. I made a copy of it in my folder with path lib/devise/models/recoverable.rb. The problem is when request to send reset password instruction, I got error undefined method activerecord51? for Devise:Module. How do i solve this?
It seems my recoverable is not in Devise module. I tried a bit by making a copy of devise.rb in lib/ folder. But it doesn't help.
Can someone please help?
EDIT
Sorry for any inconvenience. At the moment Im just trying to pass more opts to the method send_reset_password_instructions.
Any idea about this?
How about do it in some rails initializer? Your are possibly overwriting the original class/module so all the other methods are gone.
# config/initalizers/devise.rb
Devise::Models::Recoverable::ClassMethods.module_eval do
def send_reset_password_instructions(your, params)
token = set_reset_password_token
send_reset_password_instructions_notification(token)
token
end
end

Can I control when a custom Devise/Warden strategy is run with before filters?

I'm developing a web application using Rails 3.2 and am using Devise and Warden for handling authentications.
I wanted to implement a custom authentication method for my app, so I read through Warden Wiki pages (https://github.com/hassox/warden/wiki) and created a custom Warden strategy with similar structure as the one showed in its documentation (I'll copy that below for the sake of clarity):
Warden::Strategies.add(:password) do
def valid?
params['username'] || params['password']
end
def authenticate!
u = User.authenticate(params['username'], params['password'])
u.nil? ? fail!("Could not log in") : success!(u)
end
end
Following that, I added my custom "password" strategy to Devise appending the following code in config/initializers/devise.rb
config.warden do |manager|
manager.default_strategies(:scope => :user).unshift :password
end
The problem I've found is that this authentication strategy is executed on every request, and I wanted to provide free access to certain requests to specific routes in my application. Initially, I thought of preventing the execution of the strategy using
skip_before_filter :authenticate_user!
on every controller whose actions doesn't require authentication, but the authentication keeps on executing even requesting to those controllers.
Can anybody help me how to skip the authentication in some requests? Or even more important, is my idea useless to achieve what I want?
Thanks in advance for your help. I really appreciate it.
Update
While debugging my code looking for a solution, I commented out all before_filter statements in all controller's code and discovered that the authentication strategy still executes. This behaviour turns out to be really strange to me. Does this make sense to anybody?
I can remember that your "skip filter" should call the autentication method. In this case you should replace skip_before_filter :authenticate_user! by skip_before_filter :authenticate!

InvalidCrossOriginRequest when trying to send a Javascript Asset

I'm trying to create an "asset controller" shim which will filter static asset requests so only authorized users can get retrieve certain assets. I wanted to continue to use the asset pipeline so I setup a route like this
get 'assets/*assetfile' => 'assets#sendfile'
Then I created an AssetsController with one method "sendfile". Stripping it down to only the stuff that matters, it looks like this:
class AssetsController < ApplicationController
def sendfile
# Basically the following function forces the file
# path to be Rails.root/public/assets/basename
assetfilename=sanitize_filename(params[:assetfile] + '.' + params[:format])
send_file(assetfilename)
end
end
It looks like I have to run this in production mode as rails by-passes my route for assets in development. So I precompile my assets and I can verify in the controller that the files exist where they are expected to be.
However, now the problem is that I'm getting a "ActionController::InvalidCrossOriginRequest" when the Javascript asset is requested (just using the default application.* assets for now). I've read about this error and I understand that as of Rails 4.1 there are special cross-origin protections for Javascript assets. Sounds good to me, but I don't understand where the "cross-origin" part is coming from. Using firebug, I can see that the asset requests are being requested from the same domain as the original page.
I am certain that this is the problem because I can solve it by putting "skip_before_action :verify_authenticity_token" in the beginning of my controller. However, I really don't want to do this (I don't fully understand why this check is necessary, but I'm sure there are very good reasons).
The application.html.erb file is unchanged from the default generated file so I assume it's sending the CSRF token when the request is made, just as it would if I didn't have my own controller for assets.
So what am I missing?
Ok, I think I answered my own question (unsatisfactorily). Again, long post, so bear with me. I mistakenly forgot to add this to my original questions, but I'm using Ruby 2.2.0 and Rails 4.2.4.
From looking at the code in "actionpack-4.2.4/lib/action_controller/metal/request_forgery_protection.rb", it looks like Rails is doing two checks. The first check is the "verify_authenticity_token" method which does the expected validation of the authenticity token for POST requests. For GET requests, it ALSO sets a flag which causes a second check on the formed computed response to the request.
The check on the response simply says that if the request was NOT an XHR (AJAX) request AND the MIME Type of the response is "text/javascript", then raise an "ActionController::InvalidCrossOriginRequest", which was the error I was getting.
I verified this by setting the type to "application/javascript" for ".js" files in "send_file". Here's the code:
if request.format.js?
send_file(assetfilename, type: 'application/javascript')
else
send_file(assetfilename)
end
I can skip the response check all together by just adding the following line to the top of my controller class:
skip_after_action :verify_same_origin_request
The check on the response seems pretty weak to me and it's not clear how this really provides further protection against CSRF. But I'll post that in another question.

Can I get the current controller object from ApplicationController in Rails 3.1?

Is there any way I can get the controller that's about to handle the request from ApplicationController class?
Basically I'm trying to figure out a way of returning to HTTP when HTTPS is no longer required. I have configured Devise to use SSl as instructed:
#in config/environments/production.rb
config.to_prepare { Devise::SessionsController.force_ssl }
config.to_prepare { Devise::RegistrationsController.force_ssl }
However, once a Devise controller redirects to SSL it stayed there. There was a code snippet in the Devise wiki that redirects back to HTTP once a Devise action is completed. However, that won't work if user navigates away using any other means.
From my .NET way of thinking perhaps I can do something in the base class of all controllers, i.e. ApplicationController. If I can have an array of controller class names that require SSL, then redirects to HTTP if the current controller class does not require it, perhaps that will be a sufficient crude solution for now? I am a Ruby and Rails newbie so I may not be looking at this the right way at all...
Thanks,
Dany.
You can see the current controller name in the params hash: params[:controller].
You can also run controller_name
[3] pry(#<PostsController>)> controller_name
=> "posts"

Rails request forgery protection settings

please help a newbie in Rails :) I have protect_from_forgery call (which is given by default) with no attributes in my ApplicationController class.
Basically here's the code:
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery
helper_method :current_user_session, :current_user
filter_parameter_logging :password, :password_confirmation
What I assume it should do is: it should prevent any POST requests without correct authenticity_token. But when I send post request with jQuery like the one below, it works fine (there's update statement that is executed in the database)!
$.post($(this).attr("href"), { _method: "PUT", data: { test: true } });
I see in console that there's no authenticity_token among sent parameters, but request is still considered valid. Why is that?
UPD
Found config setting in config/environments/development.rb
config.action_controller.consider_all_requests_local = true
Because of the DEV environment and local requests, these jQuery post requests were OK.
There is nothing wrong with your code as long as the request $.post($(this).attr("href"), { _method: "PUT", data: { test: true } }); is executed from within the app itself. If you had another app running elsewhere, say for example on localhost:3001, and you sent a post from there then it won't work. Infact if you are on firefox > 3.0 it has an early implementation of cross site xhr too. For example you can send a POST from any other site (but this works provided protect_from_forgery is turned off!). The reason why auth token is not necessary for xhr is that cross site xhr is disabled. So it is safe to use xhr without providing auth token. If you try from any where else other than your app, i am sure it will raise an exception asking for an auth token. Also you should have a crossdomain.xml defined to prevent access from outside sources.
Try doing this: curl -X -d url_endpoint_of_your_app. See if you get a 200 response code. If you do then there is something fishy.
Silly question, perhaps: Are you sure you're subclassing ApplicationController? What's your route map look like? And what version of Rails (just for clarity)?
Did you verify that the call from jQuery is actually a POST and not a GET? (I know, it seems obvious). Rails will only perform the protection on non-GET requests.
Also, what is the content-type of the request that's going out. Rails will also only perform the protection, according to the docs, if it's an HTML/Javascript request.

Resources