module Authbox
This module adds support for Authbox
to your Rails controller. We recommend you add it to app/controllers/application_controller.rb
like this:
require 'authbox' class ApplicationController < ActionController::Base include Authbox end
Once this is included in your controller, you’ll need to add your credentials. Add them to config/application.rb like this:
config.authbox = { :api_key => 'yourApiKey', :secret_key => 'yourSecret' }
That’s it! Authbox
can start logging basic metadata immediately.
To get the most out of Authbox
you should tell us who your users are. You do this by overriding the authbox_get_request_data
() method on the controller. Here’s how you would tell Authbox
about your users while using Devise:
class ApplicationController < ActionController::Base include Authbox def authbox_get_request_data return { '$user' => { '$creationTime' => current_user.created_at, '$userIDs' => [ {'$type' => '$email', '$key' => current_user.email} ] } } end end
Private Class Methods
# File lib/authbox.rb, line 105 def self.authbox_pool if @authbox_pool.nil? @authbox_pool = Thread.pool(Rails.configuration.authbox[:threads] || 5) end return @authbox_pool end
Public Instance Methods
# File lib/authbox.rb, line 70 def authbox_check(action={}) if not authbox_ensure_one_request(:check) return @authbox_verdict end @authbox_check_action = action return authbox_request('/action_check', action, false) end
Override me to return additional data for the request (like the user)
# File lib/authbox.rb, line 99 def authbox_get_request_data return {} end
Report a custom action to Authbox
. If this is not called during a request, an $unknown action will be logged. See the documentation for what information you can pass here in the action hash.
# File lib/authbox.rb, line 57 def authbox_log(action={}) if not authbox_ensure_one_request(:log) return end if not @authbox_verdict.blank? and @authbox_verdict['type'] != 'ALLOW' return end return authbox_request('/action_log', action, true) end
Override me to inject a custom HTTP POST library
# File lib/authbox.rb, line 81 def authbox_post_form(uri, body) authbox_debug_log {"Posting data to #{uri}: #{body}"} req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'}) req.body = body.to_json return Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http| begin http.request(req) rescue => e authbox_warn_log { "HTTP request error: #{e}" } end end end
Private Instance Methods
# File lib/authbox.rb, line 245 def authbox_after if not @authbox_fired[:log] authbox_log @authbox_check_action if @authbox_insert_pixel and Rails.configuration.authbox.fetch(:enable_tracking_pixel, true) endpoint = authbox_get_endpoint() local_machine_id = cookies[authbox_get_cookie('local_machine_id')] pixel_markup = "<iframe src='#{endpoint}/pixel?LMID=#{local_machine_id}' width='0' height='0' style='border: none' />" prev_length = response.body.length response.body = response.body.gsub(/(<\/body>)/i, pixel_markup + '\1') if response.body.length > prev_length # we actually inserted the pixel, so send the cookie cookies[authbox_get_cookie('did_get_pixel')] = '1' end end end end
# File lib/authbox.rb, line 236 def authbox_before @authbox_fired = { :check => false, :log => false } @authbox_check_action = {} @authbox_insert_pixel = rand() < 0.01 end
# File lib/authbox.rb, line 112 def authbox_debug_log(&message_block) # Rails doesn't have a great way to filter logging out of the box and we want # this SDK to be as out-of-the-way as possible, so we gate all logging behind a # config. if Rails.configuration.authbox[:debug] logger.tagged('AUTHBOX') { logger.debug message_block } end end
# File lib/authbox.rb, line 140 def authbox_ensure_one_request(type) if @authbox_fired[type] authbox_warn_log { 'authbox_log() already called' } return false end @authbox_fired[type] = true return true end
# File lib/authbox.rb, line 136 def authbox_get_endpoint return Rails.configuration.authbox[:endpoint] || 'https://api.authbox.io/api' end
# File lib/authbox.rb, line 150 def authbox_request(endpoint, action, async) cookie_name = authbox_get_cookie('local_machine_id') if Rails.configuration.authbox[:api_key].nil? or Rails.configuration.authbox[:secret_key].nil? authbox_warn_log { 'api_key and secret_key were not set' } end if cookies[cookie_name].blank? local_machine_id = SecureRandom.hex(32) @authbox_new_local_machine_id = true @authbox_insert_pixel = true else local_machine_id = cookies[cookie_name] @authbox_new_local_machine_id = false end cookies[cookie_name] = { :value => local_machine_id, :expires => 2.years.from_now, :httponly => true, :domain => :all } if cookies[authbox_get_cookie('did_get_pixel')].blank? @authbox_insert_pixel = true end remote_ip = request.remote_ip body = { '$actionName' => '$unknown', '$localMachineID' => { '$key' => local_machine_id, '$new' => @authbox_new_local_machine_id }, '$userAgent' => request.user_agent, '$host' => request.host, '$referer' => request.referer, '$ipAddress' => remote_ip, '$endpointURL' => request.original_url, '$apiKey' => Rails.configuration.authbox[:api_key], '$secretKey' => Rails.configuration.authbox[:secret_key], '$rails' => { '$controller' => controller_name, '$action' => action_name } } body.merge!(authbox_get_request_data()) body.merge!(action) base_uri = authbox_get_endpoint() uri = URI(base_uri + endpoint) if async Authbox.authbox_pool.process do authbox_post_form(uri, body) end return end response = authbox_post_form(uri, body) begin parsed_response = JSON.parse(response.body) if not parsed_response.has_key? 'type' @authbox_verdict = {'type' => 'ALLOW', 'info' => 'No verdict returned'} return @authbox_verdict end rescue => e authbox_warn_log { "Error decoding body: #{e}" } # Fail open @authbox_verdict = {'type' => 'ALLOW', 'info' => 'Error from server'} return @authbox_verdict end @authbox_verdict = parsed_response return @authbox_verdict end
# File lib/authbox.rb, line 123 def authbox_warn_log(&message_block) logger.tagged('AUTHBOX') { logger.warn message_block } end