-
Notifications
You must be signed in to change notification settings - Fork 133
Endpoint authentication
The endpoint authentication use a pair (key, authentication_token).
For generate 'key' value is used NumberGenerator module.
module NumberGenerator
extend ActiveSupport::Concern
NUMBER_LENGTH = 9
NUMBER_LETTERS = false
NUMBER_PREFIX = 'N'
included do
field :number, type: String
validates :number, uniqueness: true
before_validation :generate_number, on: :create
end
def self.by_number(number)
where(number: number)
end
def generate_number(options = {})
options[:length] ||= NUMBER_LENGTH
options[:letters] ||= NUMBER_LETTERS
options[:prefix] ||= NUMBER_PREFIX
possible = (0..9).to_a
possible += ('A'..'Z').to_a if options[:letters]
self.number ||= loop do
# Make a random number.
random = "#{options[:prefix]}#{(0...options[:length]).map { possible.shuffle.first }.join}"
# Use the random number if no other order exists with it.
if self.number.present? && self.number == random
# If over half of all possible options are taken add another digit.
options[:length] += 1 if self.class.count > (10 ** options[:length] / 2)
else
break random
end
end
end
endThe module decorate Connection class.
module Setup
class Connection < Base
include NumberGenerator
...
end
endMongoid provide alias functionality, it is uses alias 'key' for 'number' field.
field :number, as: :key, type: StringIn the above example you can reference the field by Connection#key, but the field in the database is stored as number.
the method 'generate_number' is override for change prefix to 'C'.
def generate_number(options = {})
options[:prefix] ||= 'C'
super(options)
endNow we will see how to add devise auth token to connections and how to use it in Push API authentication.
module Setup
class Connection < Base
...
devise :database_authenticatable
field :authentication_token, type: String
validates_uniqueness_of :authentication_token
...
end
endGenerate Authentication token
module Setup
class Connection < Base
...
before_save :ensure_authentication_token
def ensure_authentication_token
self.authentication_token ||= generate_authentication_token
end
...
private
def generate_authentication_token
loop do
token = Devise.friendly_token
break token unless User.where(authentication_token: token).first
end
end
...
end
endApiController has the responsibility to handler the push data request from endpoints.
Now we can review the authorization method in ApiController.
module Cenit
class ApiController < ActionController::Base
before_filter :save_request_data, :authorize
...
end
endAuthorize method
protected
def authorize
key = request.headers['X-Hub-Store']
token = request.headers['X-Hub-Access-Token']
connection = Setup::Connection.unscoped.find_by(key: key)
if connection && Devise.secure_compare(connection.authentication_token, token)
return true
else
Account.current = connection.account
response_handler = Handler.new(@message)
responder = response_handler.response('Unauthorized!', 401)
render json: responder, root: false, status: responder.code
return false
end
endNotice that we are using token authentication via header.
The named param 'X-Hub-Store' for maintained consistence with Wombat integration, but you need are cleat about that not all endpoints are store.
the param 'key' is used for find a connection.
connection = Setup::Connection.unscoped.find_by(key: key)Finally we used devise for compare the param 'token' with 'authentication_token' in DB.
Devise.secure_compare(connection.authentication_token, token)