2
votes

I am using React + Rails for a web-app, and am using Devise for users authentication. I am struggling with getting a custom Logout button to work.

In my routes.rb I have the following:

devise_for :users do
  delete '/users/sign_out' => 'devise/sessions#destroy' #I've also tried get instead of delete
end

My devise.rb is configured as follows:

config.sign_out_via = :delete

In my (React) JS .jsx file, I have the following logout function, called when the button is clicked.

function logout() {
    fetch("/users/sign_out", {method: 'delete'}).then((response) => { #I have also tried replacing delete with get
   }).then((result) => {
     window.location.href = '/';
   });
}

When I use fetch + delete, I get get a 422 error from the fetch; when I use fetch + get, I get a 404 error from the fetch. I've experimented with the various possible permutations of get/delete across the routes/devise.rb files and the .jsx file with no luck.

Specifically, from my rails console I see the following for the 422 error:

Can't verify CSRF token authenticity. Completed 422 Unprocessable Entity in 4ms (ActiveRecord: 0.5ms) 

My application controller has the following:

class ApplicationController < ActionController::Base
    protect_from_forgery with: :exception
    before_action :authenticate_user!
end 

Interestingly, if I make it:

class ApplicationController < ActionController::Base
    protect_from_forgery with: :exception
    protect_from_forgery prepend: true
    before_action :authenticate_user!
end 

Then the 422 error goes away (but the application still acts as if the user is logged in).

1
whats the error you are getting when you use fetch+delete?Sumanth Madishetty
What do you have in rails server log with method: 'delete'?Vasilisa
Can't verify CSRF token authenticity. Completed 422 Unprocessable Entity in 4ms (ActiveRecord: 0.5ms)biocompamateur
@biocompamateur, great! And what are you doing with CSRF tokens on other devise actions?Vasilisa
I'm not really doing anything with CSRF tokens (other than what's being done with builtin devise functionality)biocompamateur

1 Answers

1
votes

I have the same stack (redux/rails) , im getting a 201, not sure if its correct yet, but maybe this function will help you for the CRSF token:

    export const getMetaContent = (name) => {
    var metas = document.getElementsByTagName('meta');

    for (var i=0; i<metas.length; i++) {
      if (metas[i].getAttribute("name") == name) {
        return metas[i].getAttribute("content");
      }
    }
}
// credit : https://labs.chiedo.com/post/authenticating-your-reactjs-app-with-devise-no-extra-gems-needed/

And then my Delete request in my saga for /users/signout looks like this:

  logoutUser = () => {
    console.log("CHIIII");
    const url = "users/sign_out.json";
    const options = {
      method: 'DELETE',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      data: {
        authenticity_token: getMetaContent("csrf-token")
      }
    }
      fetch(url, options)
      .then(response => {
        resolve(response)
      })
      .catch(error => console.log(error))