Elaborating on Marcao's answer, I highly recommend placing some debugger in your CustomFailure respond method in order to better understand what is going on.
Class CustomFailure < Devise::FailureApp
def respond
binding.pry
super
end
end
If you look at the FailureApp Devise Source Code for the respond method it is super easy to understand what is going on.
def respond
if http_auth?
http_auth
elsif warden_options[:recall]
recall
else
redirect
end
end
So for example in order to return a redirect_url you would want to make sure that your respond code conditionals eventually return redirect.
However if you want to maybe return a standard 401 status as defined in the http_auth method, you want to verify that your respond method code returns http_auth.
Thus it is worth your while to look into the definition of the http_auth?
In particular, note the: request.xhr? method, which will return 0 for json requests (recall that 0 actually evaluates to true in ruby)
def http_auth?
if request.xhr?
Devise.http_authenticatable_on_xhr
else
!(request_format && is_navigational_format?)
end
end
And maybe check your initializers/devise file for config.http_authenticatable_on_xhr or config.navigational_formats in order to control the response that you want. This configuration can really affect what Devise returns and can often lead to unexpected behavior due to what it does here under the hood.