401 failure instead of redirect

677 views
Skip to first unread message

benji

unread,
Jun 8, 2010, 10:38:32 AM6/8/10
to Devise
hey we're currently developing on a flex - rails web app and have some
difficulties with default devise authentication workflow. We would
like to get back a 401 failure instead of a 302 redirect. How to
override behaviour application wide?

thanks for any help. benni

José Valim

unread,
Jun 8, 2010, 10:41:29 AM6/8/10
to Devise
Which Devise and Rails version please? If you use HTTP Basic Headers,
it should return 401.

benji

unread,
Jun 8, 2010, 11:44:17 AM6/8/10
to Devise
hmmm .. not sure. We use the latest version of devise pulled via
githup and rails 2.3.5. Actually we are working in our functional
tests right now and expect to get back 401, but we don't. By the way,
we request via XML/AMF...

benji

unread,
Jun 15, 2010, 6:39:53 PM6/15/10
to Devise
Hey, any ideas?

benji

unread,
Jun 16, 2010, 3:53:17 AM6/16/10
to Devise
and important .. we don't use http auth, but database authentication.
therefore i don't know where to write this

"warden.custom_failure! if performed?"

please give me a hint.

José Valim

unread,
Jun 16, 2010, 3:55:39 AM6/16/10
to plataforma...@googlegroups.com
Unfortunately, in Devise 1.0.7, the only way to return 401 is by using http authentication. This was fixed in Devise master (by adding navigational formats, so you can register which formats returns 401 or redirect), but it was not backported. If you want to backport it, a patch is welcome!
--
José Valim

Director of Engineering - Plataforma Tecnologia
Know more about us: http://plataformatec.com.br/en/

benji

unread,
Jun 16, 2010, 10:08:23 AM6/16/10
to Devise
hey i ve done some work but may be you can help me to fix that
failure_app.rb file
my current version looks like this, returns 401, but has some strange
body in output:

#require "action_controller/metal"

module Devise

class FailureApp# < ActionController::Metal

attr_reader :env
include Warden::Mixins::Common
cattr_accessor :default_url, :default_message, :instance_writer =>
false

delegate :flash, :to => :request

def self.call(env)
new(env).respond
end

def initialize(env)
@env = env
end

def self.default_url_options(*args)
ApplicationController.default_url_options(*args)
end

def respond
if http_auth?
http_auth
elsif warden_options[:recall]
recall
else
redirect
end
end

def http_auth
headers = {}
headers["Content-Type"] = request.format.to_s

response_body = http_auth_body

[401, headers, response_body]
end

def recall
env["PATH_INFO"] = attempted_path
flash.now[:alert] = i18n_message(:invalid)
self.response =
recall_controller.action(warden_options[:recall]).call(env)
end

def redirect
store_location!
flash[:alert] = i18n_message unless flash[:notice]
redirect_to send(:"new_#{scope}_session_path")
end

protected

def i18n_message(default = nil)
message = warden.message || warden_options[:message] || default
|| :unauthenticated

if message.is_a?(Symbol)
I18n.t(:"#{scope}.#{message}", :resource_name => scope,
:scope => "devise.failure", :default => [message,
message.to_s])
else
message.to_s
end
end

def http_auth?
!Devise.navigational_formats.include?(request.format.to_sym) ||
request.xhr?
end

def http_auth_body
method = :"to_#{request.format.to_sym}"
{}.respond_to?(method) ? { :error =>
i18n_message }.send(method) : i18n_message
end

def recall_controller
"#{params[:controller].camelize}Controller".constantize
end

def warden
env['warden']
end

def warden_options
env['warden.options']
end

def scope
@scope ||= warden_options[:scope]
end

def attempted_path
warden_options[:attempted_path]
end

# Stores requested uri to redirect the user after signing in. We
cannot use
# scoped session provided by warden here, since the user is not
authenticated
# yet, but we still need to store the uri based on scope, so
different scopes
# would never use the same uri to redirect.
def store_location!
session[:"#{scope}_return_to"] = attempted_path if request.get?
&& !http_auth?
end
end
end
Reply all
Reply to author
Forward
0 new messages