Forum: Ruby on Rails How to Catch a Status 401 with htpasswd?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
sir z. (Guest)
on 2008-10-15 22:34
Hi All,

I would love to hear your thoughts on this.

I am using the htpasswd plugin located here:
http://wota.jp/svn/rails/plugins/branches/stable/htpasswd/

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 "http://someplace.com"
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 .


THANK YOU!
sir z. (Guest)
on 2008-10-17 04:24
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.

thanks

Mm Zz wrote:
> Hi All,
>
> I would love to hear your thoughts on this.
>
> I am using the htpasswd plugin located here:
> http://wota.jp/svn/rails/plugins/branches/stable/htpasswd/
>
> 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 "http://someplace.com"
> 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.
>
Patrick S. (Guest)
on 2008-10-17 12:02
(Received via mailing list)
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.
Patrick S. (Guest)
on 2008-10-17 12:02
(Received via mailing list)
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.
sir z. (Guest)
on 2008-10-19 03:12
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 "http://www.google.com"
  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 127.0.0.1 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
http://wota.jp/svn/rails/plugins/branches/stable/h...
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.
sir z. (Guest)
on 2008-10-21 21:21
I see the following starting on line 70 of
http://wota.jp/svn/rails/plugins/branches/stable/h...
:

  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?
sir z. (Guest)
on 2008-10-29 23:01
any takers on help with this? :)

thank you
sir z. (Guest)
on 2008-10-30 09:05
Mm Zz wrote:
> any takers on help with this? :)
>
> thank you

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



Since
http://wota.jp/svn/rails/plugins/branches/stable/h...
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'] =
strongest_auth.new(htpasswd_options).server_header
    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


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.
This topic is locked and can not be replied to.