On Fri, Feb 22, 2008 at 07:39:59PM +0100, Manfred Stienstra wrote:
> On Feb 22, 2008, at 7:28 PM, Albert Ng wrote:
> 
> > looking at the blog.rb example, I see a very nice example of  
> > authentication, but the username/password is transmitted in clear  
> > text form
> >
> > My question then is, Is there an easy way of "encrypting" that  
> > information?
> 
> Well, the easiest way is to do logins over SSL. A second option could  
> be HTTP Digest Authentication, but browser support for that is flackey  
> to say the least. 

I've been using Digest myself, can't say I've run into any
problems with browser support. Browser UI for it isn't great, of
course.

I've attached a module for doing digest auth with Camping. It uses the
httpauth gem.

Use it something like this:

  Camping.goes :Foo

  module Foo
    include Camping::DigestAuth

    REALM = "foo"

    module_function

    def password_for_user(username)
      # returns the correct password for user "username"
      # or nil if the user doesn't exist
    end
  end

At the beginning of every controller method you want to be
authenticated, call the 'authenticate' method.
require "httpauth"

module Camping
  module DigestAuth
    include HTTPAuth::Digest

    class Unauthorized < RuntimeError; end

    # call this at the start of methods that require authentication
    def authenticate
      raise Unauthorized unless @user
    end

    def service(*a)
      app = Kernel.const_get(self.class.name.gsub(/^(\w+)::.+$/, '\1'))
      auth_h = @env["HTTP_AUTHORIZATION"]

      begin
        if auth_h
          credentials = Credentials.from_header(auth_h)
          user = credentials.h[:username]

          begin
            pass = app.password_for_user(user)
          rescue NameError
            raise "define #password_for_user on your app module"
          end

          if pass and
              credentials.validate(:password => pass, :method => @method.upcase)
            @user = user

            auth_info = AuthenticationInfo.from_credentials credentials
            @headers["Authentication-Info"] = auth_info.to_header
          end
        end
      rescue HTTPAuth::UnwellformedHeader
        # they probably sent eg. a Basic Authenticate header
        # just ignore it instead of exploding
      end

      super(*a)
    rescue Unauthorized
      @status = 401
      challenge = Challenge.new :realm => app::REALM, :qop => ["auth"]
      @headers["WWW-Authenticate"] = challenge.to_header

      @body = authentication_failed

      self
    end

    # override this for a nicer error message
    def authentication_failed
      @headers["Content-Type"] = "text/plain"

      "you are not authorized."
    end
  end
end

Attachment: pgpXyWjZylgl6.pgp
Description: PGP signature

_______________________________________________
Camping-list mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/camping-list

Reply via email to