Class: Ubiq::Auth

Inherits:
Object
  • Object
show all
Defined in:
lib/ubiq/auth.rb

Overview

This module implements HTTP authentication for the Ubiq platform via message signing as described by the IETF httpbis-message-signatures draft specification.

Class Method Summary collapse

Class Method Details

.build_headers(papi, sapi, endpoint, query, host, http_method) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/ubiq/auth.rb', line 12

def self.build_headers(papi, sapi, endpoint, query, host, http_method)

  # This function calculates the signature for the message, adding the Signature header
  # to contain the data. Certain HTTP headers are required for
  # signature calculation and will be added by this code as
  # necessary. The constructed headers object is returned

  # the '(request-target)' is part of the signed data.
  # it's value is 'http_method path?query'
  reqt = "#{http_method} #{endpoint}"

  # The time at which the signature was created expressed as the unix epoch
  created = Time.now.to_i

  # the Digest header is always included/overridden by
  # this code. it is a hash of the body of the http message
  # and is always present even if the body is empty
  hash_sha512 = OpenSSL::Digest::SHA512.new
  hash_sha512 << JSON.dump(query)
  digest = 'SHA-512=' + Base64.strict_encode64(hash_sha512.digest)

  # Initialize the headers object to be returned via this method
  all_headers = {}
  all_headers['user-agent'] = 'ubiq-ruby/' + Ubiq::VERSION
  # The content type of request
  all_headers['content-type'] = 'application/json'
  # The request target calculated above(reqt)
  all_headers['(request-target)'] = reqt
  # The date and time in GMT format
  all_headers['date'] = get_date
  # The host specified by the caller
  all_headers['host'] = get_host(host)
  all_headers['(created)'] = created
  all_headers['digest'] = digest
  headers = ['content-type', 'date', 'host', '(created)', '(request-target)', 'digest']

  # include the specified headers in the hmac calculation. each
  # header is of the form 'header_name: header value\n'
  # included headers are also added to an ordered list of headers
  # which is included in the message
  hmac = OpenSSL::HMAC.new(sapi, OpenSSL::Digest::SHA512.new)
  headers.each do |header|
    if all_headers.key?(header)
      hmac << "#{header}: #{all_headers[header]}\n"
    end
  end

  all_headers.delete('(created)')
  all_headers.delete('(request-target)')
  all_headers.delete('host')

  # Build the Signature header itself
  all_headers['signature']  = 'keyId="' + papi + '"'
  all_headers['signature'] += ', algorithm="hmac-sha512"'
  all_headers['signature'] += ', created=' + created.to_s
  all_headers['signature'] += ', headers="' + headers.join(' ') + '"'
  all_headers['signature'] += ', signature="'
  all_headers['signature'] += Base64.strict_encode64(hmac.digest)
  all_headers['signature'] += '"'

  return all_headers
end

.get_dateObject



84
85
86
87
# File 'lib/ubiq/auth.rb', line 84

def self.get_date
  DateTime.now.in_time_zone('GMT').strftime('%a, %d %b %Y') + ' ' +
    DateTime.now.in_time_zone('GMT').strftime('%H:%M:%S') + ' GMT'
end

.get_host(host) ⇒ Object

Only want to return port in the URI if the host contained one, otherwise let gateway resolve it



77
78
79
80
81
82
# File 'lib/ubiq/auth.rb', line 77

def self.get_host(host)
  uri = URI(host)
  ret = uri.hostname.to_s
  ret += ":#{uri.port}" if host.match(/:[0-9]+/)
  ret
end