Module: Picnic::Authentication::Basic

Defined in:
lib/picnic/authentication.rb

Overview

Picnic::Authentication::Basic provides Basic HTTP Authentication for your Camping app. The module defines a service method that only continues the request chain when proper credentials are provided by the client (browser).

Getting Started

To activate Basic Authentication for your application:

  1. Picnic-fy your Camping app (e.g: Camping.goes :your_app; YourApp.picnic!)

  2. Call YourApp.authenticate_using :basic.

  3. Define an authenticate method on your application module that takes a hash. The hash contains credentials like :username, :password, and :hostname, although future authentication modules may submit other credentials. The authenticate method should return true when the credentials are valid. Examples:

    module Blog
      def authenticate(credentials)
        credentials[:username] == 'admin' &&
          credentials[:password] == 'flapper30'
      end
      module_function :authenticate
    end
    

    or

    module Wiki
      def authenticate(credentials)
        u = credentials[:username]
        p = credentials[:password]
        Models::User.find_by_username_and_password u, p
      end
      module_function :authenticate
    end
    
  4. service sets @credentials to the credentials of the person who logged in.


This code is based on Camping::BasicAuth written by Manfred Stienstra (see www.fngtps.com/2006/05/basic-authentication-for-camping).

Instance Method Summary collapse

Instance Method Details

#read_credentialsObject

Reads the username and password from the headers and returns them.



87
88
89
90
91
92
93
# File 'lib/picnic/authentication.rb', line 87

def read_credentials
  if d = %w{REDIRECT_X_HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION}.inject([]) \
    { |d,h| @env.has_key?(h) ? @env[h].to_s.split : d }
    u,p = ::Base64.decode64(d[1]).split(':')[0..1] if d[0] == 'Basic'
    return {:username => u, :password => p}
  end
end

#service(*a) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/picnic/authentication.rb', line 95

def service(*a)
  app = Kernel.const_get self.class.name.gsub(/^(\w+)::.+$/, '\1')
  unless app.respond_to? :authenticate
    raise "Basic authentication is enabled but the 'authenticate' method has not been defined."
  end
  
  @credentials = read_credentials || {}
  
  if app.authenticate(@credentials)
    s = super(*a)
  else
    @status = 401
    headers['Content-type'] = @headers['Content-type'] || 'text/plain'
    #headers['Status'] = 'Unauthorized'
    headers['WWW-Authenticate'] = "Basic realm=\"#{app}\""
    @body = 'Unauthorized'
    s = self
  end
  s
end