module ApiAuthenticator

Constants

PATH_REQUEST_TYPE
REQUEST_TYPES
URL_REQUEST_TYPE
VERSION

Public Class Methods

authenticated_request?(request) click to toggle source

authenticated_request?

Returns: True or False

# File lib/api_authenticator/authenticated_request.rb, line 8
def self.authenticated_request?(request)
  time = nil
  token = request.headers['API-Token']
  begin
    time = DateTime.parse(request.headers['API-Time'])
  rescue ArgumentError, TypeError
  end
  valid_api_time?(time)
  valid_api_token?(originating_request(request), time, token)
end
configure() { |self| ... } click to toggle source
# File lib/api_authenticator/configuration.rb, line 8
def self.configure
  yield self
end
logger() click to toggle source
# File lib/api_authenticator/configuration.rb, line 47
def self.logger
  @@logger || Logger.new($stdout)
end
logger=(logger) click to toggle source
# File lib/api_authenticator/configuration.rb, line 43
def self.logger=(logger)
  @@logger = logger || Logger.new($stdout)
end
report_unauthenticated_requests=(report) click to toggle source
# File lib/api_authenticator/configuration.rb, line 39
def self.report_unauthenticated_requests=(report)
  @@report_unauthenticated_requests = report || false
end
request_type() click to toggle source
# File lib/api_authenticator/configuration.rb, line 20
def self.request_type
  @@request_type
end
request_type=(request_type) click to toggle source
# File lib/api_authenticator/configuration.rb, line 24
def self.request_type=(request_type)
  unless REQUEST_TYPES.include?(request_type)
    raise ArgumentError.new("Request types must be one of the following #{REQUEST_TYPES.join(', ')}}")
  end
  @@request_type = request_type
end
shared_secret_keys() click to toggle source
# File lib/api_authenticator/configuration.rb, line 16
def self.shared_secret_keys
  @@shared_secret_keys
end
shared_secret_keys=(shared_secret_keys) click to toggle source
# File lib/api_authenticator/configuration.rb, line 12
def self.shared_secret_keys=(shared_secret_keys)
  @@shared_secret_keys = shared_secret_keys
end
time_threshold() click to toggle source
# File lib/api_authenticator/configuration.rb, line 35
def self.time_threshold
  @@time_threshold
end
time_threshold=(time_threshold) click to toggle source
# File lib/api_authenticator/configuration.rb, line 31
def self.time_threshold=(time_threshold)
  @@time_threshold = time_threshold
end

Protected Class Methods

originating_request(request) click to toggle source
# File lib/api_authenticator/authenticated_request.rb, line 21
def self.originating_request(request)
  if request_type == PATH_REQUEST_TYPE
    request.original_fullpath
  else
    request.original_url
  end
end
valid_api_time?(time) click to toggle source
# File lib/api_authenticator/authenticated_request.rb, line 29
def self.valid_api_time?(time)
  return false if time.nil?
  utc_now = DateTime.now.new_offset(0)

  lower_threshold = utc_now - time_threshold
  upper_threshold = utc_now + time_threshold

  if time < lower_threshold || time > upper_threshold
    raise InvalidTimeError.new(upper_threshold, lower_threshold, time)
  end
end
valid_api_token?(request_url, time, token) click to toggle source
# File lib/api_authenticator/authenticated_request.rb, line 41
def self.valid_api_token?(request_url, time, token)
  digest = OpenSSL::Digest.new('sha256')
  keys_and_tokens = []
  shared_secret_keys.each do |secret_key|
    expected_token = OpenSSL::HMAC.hexdigest(digest, secret_key, "#{time}#{request_url}")
    if defined?(ActiveSupport)
       return true if ActiveSupport::SecurityUtils.secure_compare(expected_token, token)
    else
      return true if expected_token == token
    end
    keys_and_tokens << [secret_key, token, expected_token]
  end

  raise InvalidTokenError.new(time, keys_and_tokens)
end

Public Instance Methods

api_authenticator() click to toggle source

Before filter

# File lib/api_authenticator/api_authenticator.rb, line 9
def api_authenticator
  begin
    ApiAuthenticator.authenticated_request?(request)
  rescue BaseError => e
    report_unauthenticated_requests(e)
    render( status: 401, nothing: true ) and return false
  end
end

Protected Instance Methods

report_unauthenticated_requests(e) click to toggle source

TODO: more stuff in here

# File lib/api_authenticator/api_authenticator.rb, line 21
def report_unauthenticated_requests(e)
  ApiAuthenticator.logger.warn("failed request #{e.constructed_message}")
end