1

My task is to write a feature in a javascript package that will be embedded in html sites for form validation. Validation will be done through API call to my server.

The question is how to transfer and validate CSRF token from JS to my Rails server.

I've tried doing this:

var token = function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))};

$.ajax({
    url: 'http://localhost:3000/csrf-check',
    type: 'POST',
    beforeSend: token,
    data: {
        hey: 'hey'
    },
    success: function(response) {
        console.log(response);
    }
})

In my ValidatorController:

class ValidatorController < ApplicationController
  protect_from_forgery

  def csrf_check
    if session[:_csrf_token]
      render json: :ok
    else
      render json: :fail
    end
  end
end

How can I send CSRF token and validate it on Rails server?

max
  • 96,212
  • 14
  • 104
  • 165
RomanOks
  • 692
  • 3
  • 13

2 Answers2

2

First of all: I don't really understand why you'd want to do such a thing – see max' comment.

Either way, if you want to do some kind of manual check for the authenticity token, you need to disable Rails' own facilities for this particular endpoint and then use the logic behind it in your endpoint. While I haven't tested it, I'd assume something like this should work:

class CsrfTokenChecksController < ApplicationController
  skip_forgery_protection

  def show
    head any_authenticity_token_valid? ? :ok : :bad_request
  end
end

This uses the any_authenticity_token_valid? method (see https://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html#method-i-any_authenticity_token_valid-3F) which is used internally by Rails as part of its forgery protection filter.

Note: This method exists since Rails 5. If you're using Rails 4, you'd have to go with valid_authenticity_token?(session, request.headers['X-CSRF-Token']) instead. For Rails 3, it would be form_authenticity_token == request.headers['X-CSRF-Token'].

Clemens Kofler
  • 1,878
  • 7
  • 11
1

I would consider if CSRF protection is really even applicable in your case.

Rails CSRF protection serves to guard against cross site reference forgery where another page pretends to be your page by looking visually similar and fooling the user into performing a POST request to for example steal the cookies for a replay attack.

It only actually works in the case where Rails is actually rendering the HTML as it just gives a guarantee that the the request originated from the same server that rendered the form.

If you're making something cross site on purpose it just won't work or even fill any purpose. There are other mechanisms like API keys that can be used instead to verify that the request is legit.

max
  • 96,212
  • 14
  • 104
  • 165
  • https://stackoverflow.com/questions/35181340/rails-cant-verify-csrf-token-authenticity-when-making-a-post-request/35184796#35184796 – max Jul 27 '20 at 10:26