Rails: Unable to authenticate CSRF token while executing POST request

I want to make a POST request for my local developer, for example:

  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 setting up routes, it's pretty 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? Disabling CSRF will certainly work, but I think it should be my mistake when creating such an API.

Is there any other setup I need to do?

+67
ruby-on-rails
03 Feb '16 at 15:40
source share
5 answers

Cross-site request forgery (CSRF / XSRF) is when a malicious web page tricks users into executing a request that isnโ€™t intended, for example, using bookmarklets, frames, or simply by creating a page that is visually similar enough to trick users.

Rails CSRF protection is for classic web applications โ€” it simply gives you a certain degree of confidence that the request came from your own web application. The 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 through hidden input, and Rails checks that any non-GET request includes a token that matches what is stored in the session.

However, the API is, by definition, usually cross-site and not just for your web application, which means the CSRF concept is not entirely applicable.

Instead, you should use a token-based API request authentication strategy with an API key and secret, as you verify that the request comes from an approved API client, and not from your own application.

You can deactivate CSRF as indicated by @dcestari:

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

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

 rails new appname --api 

They do not include CSRF middleware and many other components that are super fluxing.

+86
03 Feb '16 at 18:26
source share

Another way to disable the CSRF function, which will not display a null session, is to add:

 skip_before_action :verify_authenticity_token 

in your Rails Controller. This will provide you access to session information.

Again, make sure that you only do this on API controllers or in other places where CSRF protection is not entirely applicable.

+58
Mar 30 '17 at 15:40
source share

There is relevant CSRF configuration information regarding API controllers at api.rubyonrails.org :

โ‹ฎ

It is important to remember that XML or JSON requests are also affected, and if you create an API, you must change the fake protection method in the ApplicationController (default :exception ):

 class ApplicationController < ActionController::Base protect_from_forgery unless: -> { request.format.json? } end 

We can disable CSRF protection for the API, as they are usually designed to be inactive. That is, the request API client will process the session for you instead of Rails.

โ‹ฎ

+16
Apr 21 '18 at 20:08
source share

In Rails 5, you can also create a new class with :: API instead of :: Base:

 class ApiController < ActionController::API end 
+6
Dec 04 '18 at 15:17
source share

If you want to exclude the action pattern of the controller pattern

 class TestController < ApplicationController protect_from_forgery :except => [:sample] def sample     render json: @hogehoge end end 

You can handle requests from the outside without problems.

+2
Dec 13
source share



All Articles