Reputation: 35
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).
Upvotes: 2
Views: 1409
Reputation: 144
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))
Upvotes: 1