module Authy
Api Authentication Module
¶ ↑
How it works
¶ ↑
Client Side
¶ ↑
A string is first created using your HTTP payload containing all parameters and a preshared key. This string is then used to create the signature which is a Base64 encoded SHA1 HMAC, using the clients private secret key. This signature is then can be added to Authorization HTTP header Authorization = Authy.generate_signed_header(params)
You can pass explicite service name and shared_key as an argument to support multiple API authentication Authorization = Authy.generate_signed_header(params, 'client_1', ENV['client_1_shared_key'])
Now add this to to your header header["Authorization"] = Authorization
secret_key generated from the server side can be kept inside the a environment variable with name shared_key along with service_name as your service name
Server Side API validation is_valid = Authy.validate_api(params, request.headers)
Pass explicite shared key to support multiple API authentication is_valid = Authy.validate_api(params, request.headers,ENV['client_1_shared_key'])
Generating secret key for clients secret_key = Authy.generate_secret_key
Public Class Methods
# File lib/authi.rb, line 70 def self.fully_qualified_keys_2(object, fully_qualified_keys = [], val = '', prefix = nil, map = {}) if object.is_a? Hash object.each do |key, val| key_ = prefix.nil? ? key : prefix + '[' + key + ']' Authy.fully_qualified_keys_2(val, fully_qualified_keys, val, key_, map) end elsif object.is_a? Array object.each_with_index do |item, index| key_ = prefix + '[' + index.to_s + ']' Authy.fully_qualified_keys_2(item, fully_qualified_keys, item, key_, map) end else map[prefix] = val.to_s fully_qualified_keys << prefix end [fully_qualified_keys.join(','), map] end
Generate a pre-shared key for client
Example:
>> Authy.generate_secret_key => "63SnNesbvA9IuwXlkpF9KA=="
# File lib/authi.rb, line 115 def self.generate_secret_key SecureRandom.base64 end
Create a signed hash using input parameter
Example:
>> Authy.generate_signed_header({ 'key' => value }) => {:"X-OWNING-SERVICE"=>"l", :"X-SIGNING-ORDER"=>"", :"X-SIGNATURE"=>""}
Arguments:
data: (map)
# File lib/authi.rb, line 36 def self.generate_signed_header(data, service_name = ENV['service_name'], shared_key = ENV['shared_key']) processed_data, deep_lookup_table = Authy.fully_qualified_keys(data) signing_order = processed_data + ',' + 'owning_service,signing_order' request_data = Authy.build_query(processed_data, deep_lookup_table) unsigned_data = request_data + \ '&owning_service=' + service_name + '&signing_order=' + \ signing_order digest = OpenSSL::Digest.new('sha1') hmac = OpenSSL::HMAC.digest(digest, shared_key, unsigned_data) signed_str = Base64.strict_encode64(hmac) { 'X-OWNING-SERVICE': service_name, 'X-SIGNING-ORDER': signing_order, 'X-SIGNATURE': signed_str } end
Validate API
Example:
>> Authy.validate_api(params, request.headers) => true/false
Arguments:
params: (map) header
# File lib/authi.rb, line 104 def self.validate_api(params, header, shared_key = ENV['shared_key']) owning_service = header['Authorization'][:'X-OWNING-SERVICE'] expected_header = Authy.generate_signed_header(params, owning_service, shared_key) expected_header[:'X-SIGNATURE'] == header['Authorization'][:'X-SIGNATURE'] end