def authenticate_user_request(request, user_lookup, time_skew=(15*60))
Mixlib::Authentication::Log.debug "Initializing header auth : #{request.inspect}"
headers ||= request.env.inject({ }) { |memo, kv| memo[$2.gsub(/\-/,"_").downcase.to_sym] = kv[1] if kv[0] =~ /^(HTTP_)(.*)/; memo }
digester = Mixlib::Authentication::Digester
begin
@allowed_time_skew = time_skew
@http_method = request.method.to_s
@path = request.path.to_s
@signing_description = headers[:x_ops_sign].chomp
@user_id = headers[:x_ops_userid].chomp
@timestamp = headers[:x_ops_timestamp].chomp
@host = headers[:host].chomp
@content_hash = headers[:x_ops_content_hash].chomp
@user_secret = user_lookup
@request_signature = headers.find_all { |h| h[0].to_s =~ /^x_ops_authorization_/ }.sort { |x,y| x.to_s <=> y.to_s}.map { |i| i[1] }.join("\n")
Mixlib::Authentication::Log.debug "Reconstituted request signature: #{@request_signature}"
file_param = request.params.values.find { |value| value.respond_to?(:read) }
if file_param.nil?
hash_param = request.params.values.find { |value| value.respond_to?(:has_key?) }
if !hash_param.nil?
file_param = hash_param.values.find { |value| value.respond_to?(:read) }
end
end
if file_param
Mixlib::Authentication::Log.debug "Digesting file_param: '#{file_param.inspect}'"
@hashed_body = digester.hash_file(file_param)
else
body = request.raw_post
Mixlib::Authentication::Log.debug "Digesting body: '#{body}'"
@hashed_body = digester.hash_string(body)
end
Mixlib::Authentication::Log.debug "Authenticating user : #{user_id}, User secret is : #{@user_secret}, Request signature is :\n#{@request_signature}, Hashed Body is : #{@hashed_body}"
parse_signing_description
candidate_block = canonicalize_request
request_decrypted_block = @user_secret.public_decrypt(Base64.decode64(@request_signature))
signatures_match = (request_decrypted_block == candidate_block)
timeskew_is_acceptable = timestamp_within_bounds?(Time.parse(timestamp), Time.now)
hashes_match = @content_hash == hashed_body
rescue StandardError=>se
raise StandardError,"Failed to authenticate user request. Most likely missing a necessary header: #{se.message}", se.backtrace
end
Mixlib::Authentication::Log.debug "Candidate Block is: '#{candidate_block}'\nRequest decrypted block is: '#{request_decrypted_block}'\nCandidate content hash is: #{hashed_body}\nRequest Content Hash is: '#{@content_hash}'\nSignatures match: #{signatures_match}, Allowed Time Skew: #{timeskew_is_acceptable}, Hashes match?: #{hashes_match}\n"
if signatures_match and timeskew_is_acceptable and hashes_match
OpenStruct.new(:name=>user_id)
else
nil
end
end