How to Catch a Status 401 with htpasswd?

Hi All,

I would love to hear your thoughts on this.

I am using the htpasswd plugin located here:

To validate access against a .htpasswd file. The plugin is working great but currently if you fail to get the PW correct and generate a 401 (Unauthorized) the user is presented with a completely blank page.

My goal is to at least redirect them to the home page or present a message saying their login attempts have failed.

Here is what i have tried: #application.rb   rescue_from Htpasswd::UnknownUserAccount, :with => :http_status_code

def http_status_code   redirect_to "" end

^---- The above does nothing and does NOT catch anything. I have tried with Htpasswd::Error, and ActiveResource::UnauthorizedAccess -- nothing.

I have also tried a before filter with a method in application.rb calling htpasswd but i get an error saying the htpasswd method does not exist.

Any input or even a starting place where i can begin researching would be great .


If anyone has a suggestion for a starting point on where I can begin trying to figure this out i'd really appreciate hearing it.


Mm Zz wrote:

In ./lib/htpasswd/auths/base.rb I found two exceptions that are raised for an invalid account and password: Htpasswd::UnknownUserAccount and Htpasswd::IncorrectPassword.

Try rescuing the latter. See if that does the trick.

Sorry for replying twice... caught this after I sent the first one.

All of your error classes are in ./lib/htpasswd/class_methods.rb:

  class Error < StandardError; end   class HeaderNotFound < Error; end   class UnknownSchemeError < Error; end   class NotAuthorizedError < Error; end   class ConfigurationError < Error; end

  class UnknownAccessControl < ConfigurationError; end   class AuthSchemesNotDefined < ConfigurationError; end   class IncorrectPassword < NotAuthorizedError; end   class UnknownUserAccount < NotAuthorizedError; end

There's your two classes at the bottom. I would suggest rescuing Htpasswd::NotAuthorizedError, so that you catch both incorrect passwords and unknown accounts. That would be a more secure way to go, so you don't inadvertently reveal which user accounts are valid.

Hi Patrick,

Thank you so much for taking the time to look into the plugin's code and offering advice.

I gave it a shot and it appears my rescue_from is being ignored:

This is what i have in application.rb (just for testing)

  ##application.rb   rescue_from Htpasswd::NotAuthorizedError, :with => :badlogin   def badlogin     redirect_to ""   end

when the pw box comes up, i put in bad login info... and it just loops infinitely prompting me with the login/pw fields.

In my server log i have this over and over:

Processing PostsController#index (for at 2008-10-18 15:54:41) [GET]   Session ID: BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo SGFzaHsABjoKQHVzZWR7AA==--b13da02c3dcb245cb43911897a5d940881991d88   Parameters: {"action"=>"index", "controller"=>"posts"} Htpasswd is enabled with {:schemes=>#<Set: {:basic}>} Htpasswd accepts authorization header: 'Basic YXdlZmF3ZWY6' Htpasswd error(Htpasswd::UnknownUserAccount): Htpasswd::UnknownUserAccount Htpasswd sending authenticate header: 'Basic realm="Authorization"' Filter chain halted as [:htpasswd_authorize] rendered_or_redirected. Completed in 0.00386 (259 reqs/sec) | Rendering: 0.00101 (26%) | DB: 0.00000 (0%) | 401 Unauthorized [http://localhost/posts\]

Looking at the bottom of it appears the plugin is rescuing it's own error?

Do you think it is stepping in before my "rescue_from"? If so, is it possible to work around that some how?

thx again.

I see the following starting on line 70 of :

  rescue Htpasswd::Error => error     logger.debug "Htpasswd error(%s): %s" % [error.class, error.message]

Since i do notice this debug statement is printed in my dev log, is it safe to say the error is rescued before my "rescue_from" is triggered?

any takers on help with this? :slight_smile:

thank you

Mm Zz wrote:

any takers on help with this? :slight_smile:

thank you

Here is the solution thanks to an Awesome gent in #rubyonrails....

Since is rescuing Htpasswd::Error => error around line 70, i overrode the htpasswd_authorize method by doing the following:

- Created lib/hacks/htpasswd_hack.rb - Dropped the following into that file: module Htpasswd

  protected   def htpasswd_authorize     logger.debug "Htpasswd is enabled with %s" % htpasswd_options.inspect     username = Auths.scheme(self).authorize(htpasswd_acls)     logger.debug "Htpasswd authorize user '%s'" % username     @htpasswd_authorized_username = username     return true   rescue Htpasswd::Error => error     logger.debug "Htpasswd error(%s): %s" % [error.class, error.message]     strongest_auth = htpasswd_options[:schemes].map{|scheme| Auths[scheme]}.sort.last or raise AuthSchemesNotDefined     response.headers['WWW-Authenticate'] =     logger.debug "Htpasswd sending authenticate header: '%s'"% response.headers['WWW-Authenticate']

    #render :nothing => true, :status => 401     # DO SOMETHING FANCY WITH THE 401 HERE     render :action => "show_home_page", :layout=> false , :status => 401     return false   end


- In application.rb added this on line 1: require 'lib/hacks/htpasswd_hack'

And finally i ended all that by dancing a jig.

THANKS to Patrick for responding to my help request.