Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Can't verify CSRF token authenticity when making a POST request

I want to make POST request to my local dev, like this:

  HTTParty.post('http://localhost:3000/fetch_heroku',                 :body => {:type => 'product'},) 

However, from the server console it reports

Started POST "/fetch_heroku" for 127.0.0.1 at 2016-02-03 23:33:39 +0800   ActiveRecord::SchemaMigration Load (0.0ms)  SELECT "schema_migrations".* FROM "schema_migrations" Processing by AdminController#fetch_heroku as */*   Parameters: {"type"=>"product"} Can't verify CSRF token authenticity Completed 422 Unprocessable Entity in 1ms 

Here is my controller and routes setup, it's quite simple.

  def fetch_heroku     if params[:type] == 'product'       flash[:alert] = 'Fetch Product From Heroku'       Heroku.get_product     end   end    post 'fetch_heroku' => 'admin#fetch_heroku' 

I'm not sure what I need to do? To turn off the CSRF would certainly work, but I think it should be my mistake when creating such an API.

Is there any other setup I need to do?

like image 691
cqcn1991 Avatar asked Feb 03 '16 15:02

cqcn1991


People also ask

How does rails verify CSRF token?

When a user makes a POST request, the CSRF token from the HTML gets sent with that request. Rails compares the token from the page with the token from the session cookie to ensure they match.

How authenticity token works in Rails?

When the user submits the form, Rails looks for the authenticity_token , compares it to the one stored in the session, and if they match the request is allowed to continue. Since the authenticity token is stored in the session, the client cannot know its value.

What are CSRF tokens?

A CSRF token is a secure random token (e.g., synchronizer token or challenge token) that is used to prevent CSRF attacks. The token needs to be unique per user session and should be of large random value to make it difficult to guess. A CSRF secure application assigns a unique CSRF token for every user session.


1 Answers

Cross site request forgery (CSRF/XSRF) is when a malicious web page tricks users into performing a request that is not intended for example by using bookmarklets, iframes or just by creating a page which is visually similar enough to fool users.

The Rails CSRF protection is made for "classical" web apps - it simply gives a degree of assurance that the request originated from your own web app. A CSRF token works like a secret that only your server knows - Rails generates a random token and stores it in the session. Your forms send the token via a hidden input and Rails verifies that any non GET request includes a token that matches what is stored in the session.

However an API is usually by definition cross site and meant to be used in more than your web app, which means that the whole concept of CSRF does not quite apply.

Instead you should use a token based strategy of authenticating API requests with an API key and secret since you are verifying that the request comes from an approved API client - not from your own app.

You can deactivate CSRF as pointed out by @dcestari:

class ApiController < ActionController::Base   protect_from_forgery with: :null_session end 

Updated. In Rails 5 you can generate API only applications by using the --api option:

rails new appname --api 

They do not include the CSRF middleware and many other components that are superflouus.

  • http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf
  • https://labs.kollegorna.se/blog/2015/04/build-an-api-now/
  • WARNING: Can't verify CSRF token authenticity rails
like image 137
max Avatar answered Oct 16 '22 03:10

max