Jimbo did an awesome job explaining the “why” behind the issue you’re running into. There are two approaches you can take to resolve the issue:
-
(As recommended by Jimbo) Override Devise::SessionsController to return the new csrf-token:
class SessionsController < Devise::SessionsController def destroy # Assumes only JSON requests signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)) render :json => { 'csrfParam' => request_forgery_protection_token, 'csrfToken' => form_authenticity_token } end end
And create a success handler for your sign_out request on the client side (likely needs some tweaks based on your setup, e.g. GET vs DELETE):
signOut: function() { var params = { dataType: "json", type: "GET", url: this.urlRoot + "/sign_out.json" }; var self = this; return $.ajax(params).done(function(data) { self.set("csrf-token", data.csrfToken); self.unset("user"); }); }
This also assumes you’re including the CSRF token automatically with all AJAX requests with something like this:
$(document).ajaxSend(function (e, xhr, options) { xhr.setRequestHeader("X-CSRF-Token", MyApp.session.get("csrf-token")); });
-
Much more simply, if it is appropriate for your application, you can simply override the
Devise::SessionsController
and override the token check withskip_before_filter :verify_authenticity_token
.