lib/rack/simple_auth/hmac.rb in rack-simple_auth-0.1.0 vs lib/rack/simple_auth/hmac.rb in rack-simple_auth-0.1.1
- old
+ new
@@ -8,115 +8,120 @@
# @param [Hash] config [config hash where tolerance, secret, signature etc.. are set]
def initialize(app, config)
@app = app
@signature = config['signature'] || ''
@secret = config['secret'] || ''
- @tolerance = config['tolerance'] || 0 # 0 if tolerance not set in config hash
+ @tolerance = config['tolerance'] || 1 # 0 if tolerance not set in config hash
@logpath = config['logpath']
@steps = config['steps'] || 1
+ valid_stepsize?(0.01)
+ valid_tolerance?
+
@config = config
end
# call Method for Rack Middleware/Application
# @param [Hash] env [Rack Env Hash which contains headers etc..]
def call(env)
- request = Rack::Request.new(env)
- if valid?(request)
+ @request = Rack::Request.new(env)
+
+ if valid_request?
@app.call(env)
else
response = Rack::Response.new('Unauthorized', 401, 'Content-Type' => 'text/html')
response.finish
end
end
# checks for valid HMAC Request
- # @param [Rack::Request] request [current Request]
# @return [boolean] ValidationStatus [If authorized returns true, else false]
- def valid?(request)
- hash_array = build_allowed_messages(request)
+ def valid_request?
+ if @request.env['HTTP_AUTHORIZATION'].nil?
+ log(allowed_messages)
- if request.env['HTTP_AUTHORIZATION'].nil?
- log(request, hash_array)
-
return false
end
- auth_array = request.env['HTTP_AUTHORIZATION'].split(':')
- message_hash = auth_array[0]
- signature = auth_array[1]
-
- if signature == @signature && hash_array.include?(message_hash)
+ if request_signature == @signature && allowed_messages.include?(request_message)
true
else
- log(request, hash_array)
+ log(allowed_messages)
false
end
end
+ private
+
+ # Get request signature
+ def request_signature
+ @request.env['HTTP_AUTHORIZATION'].split(':').last
+ end
+
+ # Get encrypted request message
+ def request_message
+ @request.env['HTTP_AUTHORIZATION'].split(':').first
+ end
+
# Builds Array of allowed message hashs
- # @param [Rack::Request] request [current Request]
# @return [Array] hash_array [allowed message hashes as array]
- def build_allowed_messages(request)
- hash_array = []
+ def allowed_messages
+ messages = []
(-(@tolerance)..@tolerance).step(@steps) do |i|
i = i.round(2)
- hash_array << OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @secret, message(request, i))
+ messages << OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @secret, message(i))
end
- hash_array
+ messages
end
# Get Message for current Request and delay
- # @param [Rack::Request] request [current Request]
# @param [Fixnum] delay [delay in timestamp format]
# @return [Hash] message [message which will be encrypted]
- def message(request, delay = 0)
+ def message(delay = 0)
date = Time.now.to_i + delay
+ date = date.to_i if delay.eql?(0.0)
- if delay.eql?(0.0)
- date = date.to_i
- end
-
- case request.request_method
+ case @request.request_method
when 'GET'
- return { 'method' => request.request_method, 'date' => date, 'data' => request_data(request, @config) }.to_json
+ return { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
when 'POST'
- return { 'method' => request.request_method, 'date' => date, 'data' => request_data(request, @config) }.to_json
+ return { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
when 'DELETE'
- return { 'method' => request.request_method, 'date' => date, 'data' => request_data(request, @config) }.to_json
+ return { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
when 'PUT'
- return { 'method' => request.request_method, 'date' => date, 'data' => request_data(request, @config) }.to_json
+ return { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
when 'PATCH'
- return { 'method' => request.request_method, 'date' => date, 'data' => request_data(request, @config) }.to_json
+ return { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
end
end
# Get Request Data specified by Config
- # @param [Rack::Request] request [current Request]
# @param [Hash] config [Config Hash containing what type of info is data for each request]
# @return [String|Hash] data [Data for each request]
- def request_data(request, config)
- if config[request.request_method] == 'path' || config[request.request_method] == 'params'
- request.send(config[request.request_method].to_sym)
+ def request_data(config)
+ if config[@request.request_method] == 'path' || config[@request.request_method] == 'params'
+ @request.send(config[@request.request_method].to_sym)
else
- fail "Not a valid option #{config[request.request_method]} - Use either params or path"
+ fail "Not a valid option #{config[@request.request_method]} - Use either params or path"
end
end
# Log to @logpath if request is unathorized
- # @param [Rack::Request] request [current Request]
- def log(request, hash_array)
+ # Contains:
+ # - allowed messages and received message
+ # - time when request was made
+ # - type of request
+ # - requested path
+ def log(hash_array)
if @logpath
- path = request.path
- method = request.request_method
+ log = "#{Time.new} - #{@request.request_method} #{@request.path} - 400 Unauthorized\n"
+ log << "HTTP_AUTHORIZATION: #{@request.env['HTTP_AUTHORIZATION']}\n"
+ log << "Auth Message Config: #{@config[@request.request_method]}\n"
- log = "#{Time.new} - #{method} #{path} - 400 Unauthorized - HTTP_AUTHORIZATION: #{request.env['HTTP_AUTHORIZATION']}\n"
- log << "Auth Message Config: #{@config[request.request_method]}\n"
-
if hash_array
log << "Allowed Encrypted Messages:\n"
hash_array.each do |hash|
log << "#{hash}\n"
end
@@ -128,9 +133,23 @@
f << "#{log}\n"
end
end
end
- private :log, :request_data, :message, :valid?, :build_allowed_messages
+ # Check if Stepsize is valid, if > min ensure stepsize is min stepsize
+ # @param [float] min [minimum allowed stepsize]
+ def valid_stepsize?(min)
+ if @steps < min
+ puts "Warning: Minimum allowed stepsize is #{min}"
+ @steps = min
+ end
+ end
+
+ # Check if tolerance is valid, tolerance must be greater than stepsize
+ def valid_tolerance?
+ if @tolerance < @steps
+ fail "Tolerance must be greater than stepsize - Tolerance: #{@tolerance}, Stepsize: #{@steps}"
+ end
+ end
end
end
end