class DeviseProxy::Proxy

Attributes

authenticator[RW]
host[RW]
port[RW]

Public Class Methods

new(options = {}) click to toggle source
# File lib/devise-proxy/proxy.rb, line 14
def initialize(options = {})
              opts = {
                      'authentication' => {
                              'hostname' => 'localhost',
                              'port' => 3000},
                      'forwarding' => {
                              'hostname' => 'localhost',
                              'port' => 3000}
                      }.merge!(options)
              @host = opts['forwarding']['hostname']
              @port = opts['forwarding']['port']
              # puts "CREDS: #{opts['authentication']['hostname']}:#{opts['authentication']['port']}"
              @authenticator = DeviseProxy::Authenticator.new(opts['authentication']['hostname'], opts['authentication']['port'])
      end

Public Instance Methods

call(env) click to toggle source
# File lib/devise-proxy/proxy.rb, line 29
def call(env)
              # puts req.to_yaml
              
              puts "User agent: #{env['HTTP_USER_AGENT']}"

              client_credential_b64 = env['HTTP_PROXY_AUTHORIZATION']
              # puts "B64: #{client_credential_b64}"
              
              if client_credential_b64 != nil and client_credential_b64 != ''
                      # Decode the credentials:
                      encoded = client_credential_b64.split[1]
                      credentials = Base64.decode64(encoded).split(':', 2)
                      email = credentials[0]
                      password = credentials[1]
                      
                      #puts "Client password credentials email: #{email}, password, #{password}"

                      result = [502, {'Content-Type' => 'text/plain'}, ["HTTP 502 - Ah crap! The authenticating proxy seems to be having issues. :-/"]]
                      begin
                              # Authenticate against the backend:
                              auth =  @authenticator.authenticate(email, password)
                              allowed = auth[0].to_s == '201'
                              puts "Authenticated #{allowed ? 'approved.' : 'denied!'}\n\n"

                              result = [403, auth[1], [auth[2]]]
                              if allowed
  env['QUERY_STRING'] = [env['QUERY_STRING'], "auth_token=#{auth[3]}"].reject{|s| s.length < 1}.join('&')

  req = Rack::Request.new(env)
                          method = req.request_method.downcase
                          method[0..0] = method[0..0].upcase

                          sub_request = Net::HTTP.const_get(method).new("#{req.path}?#{req.query_string}")

                          if sub_request.request_body_permitted? and req.body
                            sub_request.body_stream = req.body
                            sub_request.content_length = req.content_length
                            sub_request.content_type = req.content_type
                          end

                          sub_request["X-Forwarded-For"] = (req.env["X-Forwarded-For"].to_s.split(/, +/) + [req.env['REMOTE_ADDR']]).join(", ")
                          sub_request["Accept-Encoding"] = req.accept_encoding
                          sub_request["Referer"] = req.referer

  all_cookies = auth[1]['set-cookie'].split(/;/)
  cookies_array = Array.new
  all_cookies.each { | cookie |
      cookies_array.push(cookie.split('; ')[0])
  }
  cookies = cookies_array.join('; ')

  sub_request["Cookie"] = cookies

                          sub_response = Net::HTTP.start(@host, @port) do |http|
                            http.request(sub_request)
                          end
                                      
                          headers = {}
                          sub_response.each_header do |k,v|
                            headers[k] = v unless k.to_s =~ /cookie|content-length|transfer-encoding|status/i
                          end

  body = sub_response.body
                          result = [sub_response.code.to_i, headers, [body]]
                              end
                      rescue Exception => e
puts e.message
                              # Probably an I/O issue connecting to the authentication service.
                      end
                      

              else
                      # The client needs to retry, next time sending proxy credentials!
                      headers = {}
          # sub_response.each_header do |k,v|
          #   headers[k] = v unless k.to_s =~ /cookie|content-length|transfer-encoding/i
          # end
                      headers['Proxy-Authenticate'] = 'Basic realm="A valid account is required. Please use your registered email address as your username."'             
                      headers['Content-Type']     = 'text/plain'
                      headers['WWW-Authenticate'] = 'Basic realm="aousntoheunth"'
          # result = [407, headers, ["Email/Password required!"]]
          result = [401, headers, ["Email/Password required!"]]
              end
              

              result
      end