api-auth 1.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/main.yml +71 -0
  3. data/.gitignore +13 -44
  4. data/.rubocop.yml +39 -0
  5. data/.rubocop_todo.yml +83 -0
  6. data/Appraisals +12 -36
  7. data/CHANGELOG.md +75 -1
  8. data/README.md +155 -52
  9. data/Rakefile +1 -1
  10. data/VERSION +1 -1
  11. data/api_auth.gemspec +35 -23
  12. data/gemfiles/rails_60.gemfile +9 -0
  13. data/gemfiles/rails_61.gemfile +9 -0
  14. data/gemfiles/rails_70.gemfile +9 -0
  15. data/lib/api-auth.rb +1 -1
  16. data/lib/api_auth/base.rb +41 -35
  17. data/lib/api_auth/errors.rb +4 -3
  18. data/lib/api_auth/headers.rb +38 -42
  19. data/lib/api_auth/helpers.rb +7 -16
  20. data/lib/api_auth/railtie.rb +34 -74
  21. data/lib/api_auth/request_drivers/action_controller.rb +27 -27
  22. data/lib/api_auth/request_drivers/action_dispatch.rb +0 -6
  23. data/lib/api_auth/request_drivers/curb.rb +16 -21
  24. data/lib/api_auth/request_drivers/faraday.rb +25 -34
  25. data/lib/api_auth/request_drivers/faraday_env.rb +102 -0
  26. data/lib/api_auth/request_drivers/grape_request.rb +87 -0
  27. data/lib/api_auth/request_drivers/http.rb +96 -0
  28. data/lib/api_auth/request_drivers/httpi.rb +22 -27
  29. data/lib/api_auth/request_drivers/net_http.rb +21 -26
  30. data/lib/api_auth/request_drivers/rack.rb +23 -28
  31. data/lib/api_auth/request_drivers/rest_client.rb +24 -29
  32. data/lib/api_auth.rb +4 -0
  33. data/lib/faraday/api_auth/middleware.rb +35 -0
  34. data/lib/faraday/api_auth.rb +8 -0
  35. data/spec/api_auth_spec.rb +135 -96
  36. data/spec/faraday_middleware_spec.rb +17 -0
  37. data/spec/headers_spec.rb +148 -108
  38. data/spec/helpers_spec.rb +8 -10
  39. data/spec/railtie_spec.rb +80 -99
  40. data/spec/request_drivers/action_controller_spec.rb +122 -79
  41. data/spec/request_drivers/action_dispatch_spec.rb +212 -85
  42. data/spec/request_drivers/curb_spec.rb +36 -33
  43. data/spec/request_drivers/faraday_env_spec.rb +188 -0
  44. data/spec/request_drivers/faraday_spec.rb +87 -83
  45. data/spec/request_drivers/grape_request_spec.rb +280 -0
  46. data/spec/request_drivers/http_spec.rb +190 -0
  47. data/spec/request_drivers/httpi_spec.rb +59 -59
  48. data/spec/request_drivers/net_http_spec.rb +70 -66
  49. data/spec/request_drivers/rack_spec.rb +101 -97
  50. data/spec/request_drivers/rest_client_spec.rb +218 -144
  51. data/spec/spec_helper.rb +15 -12
  52. metadata +144 -83
  53. data/.travis.yml +0 -40
  54. data/Gemfile.lock +0 -115
  55. data/gemfiles/rails_23.gemfile +0 -9
  56. data/gemfiles/rails_23.gemfile.lock +0 -70
  57. data/gemfiles/rails_30.gemfile +0 -9
  58. data/gemfiles/rails_30.gemfile.lock +0 -92
  59. data/gemfiles/rails_31.gemfile +0 -9
  60. data/gemfiles/rails_31.gemfile.lock +0 -98
  61. data/gemfiles/rails_32.gemfile +0 -9
  62. data/gemfiles/rails_32.gemfile.lock +0 -97
  63. data/gemfiles/rails_4.gemfile +0 -9
  64. data/gemfiles/rails_4.gemfile.lock +0 -94
  65. data/gemfiles/rails_41.gemfile +0 -9
  66. data/gemfiles/rails_41.gemfile.lock +0 -98
  67. data/gemfiles/rails_42.gemfile +0 -9
  68. data/gemfiles/rails_42.gemfile.lock +0 -115
@@ -1,17 +1,15 @@
1
1
  module ApiAuth
2
-
3
2
  # Builds the canonical string given a request object.
4
3
  class Headers
5
-
6
4
  include RequestDrivers
7
5
 
8
- def initialize(request)
6
+ def initialize(request, authorize_md5: false)
9
7
  @original_request = request
10
- @request = initialize_request_driver(request)
8
+ @request = initialize_request_driver(request, authorize_md5: authorize_md5)
11
9
  true
12
10
  end
13
11
 
14
- def initialize_request_driver(request)
12
+ def initialize_request_driver(request, authorize_md5: false)
15
13
  new_request =
16
14
  case request.class.to_s
17
15
  when /Net::HTTP/
@@ -28,54 +26,52 @@ module ApiAuth
28
26
  else
29
27
  ActionControllerRequest.new(request)
30
28
  end
29
+ when /Grape::Request/
30
+ GrapeRequest.new(request)
31
31
  when /ActionDispatch::Request/
32
- ActionDispatchRequest.new(request)
32
+ ActionDispatchRequest.new(request, authorize_md5: authorize_md5)
33
33
  when /ActionController::CgiRequest/
34
34
  ActionControllerRequest.new(request)
35
35
  when /HTTPI::Request/
36
36
  HttpiRequest.new(request)
37
37
  when /Faraday::Request/
38
38
  FaradayRequest.new(request)
39
- else
40
- nil
39
+ when /Faraday::Env/
40
+ FaradayEnv.new(request)
41
+ when /HTTP::Request/
42
+ HttpRequest.new(request)
41
43
  end
42
44
 
43
45
  return new_request if new_request
44
- return RackRequest.new(request) if request.kind_of?(Rack::Request)
45
- raise UnknownHTTPRequest, "#{request.class.to_s} is not yet supported."
46
+ return RackRequest.new(request) if request.is_a?(Rack::Request)
47
+
48
+ raise UnknownHTTPRequest, "#{request.class} is not yet supported."
46
49
  end
47
50
  private :initialize_request_driver
48
51
 
49
52
  # Returns the request timestamp
50
53
  def timestamp
51
- @request.timestamp
54
+ @request.timestamp
52
55
  end
53
56
 
54
- # Returns the canonical string computed from the request's headers
55
- def canonical_string_without_http_method
56
- [ @request.content_type,
57
- @request.content_md5,
58
- parse_uri(@request.request_uri),
59
- @request.timestamp
60
- ].join(",")
61
- end
57
+ def canonical_string(override_method = nil, headers_to_sign = [])
58
+ request_method = override_method || @request.http_method
62
59
 
63
- # temp backwards compatibility
64
- alias_method :canonical_string, :canonical_string_without_http_method
60
+ raise ArgumentError, 'unable to determine the http method from the request, please supply an override' if request_method.nil?
65
61
 
66
- def canonical_string_with_http_method(override_method = nil)
67
- request_method = override_method || @request.http_method
62
+ headers = @request.fetch_headers
63
+
64
+ canonical_array = [request_method.upcase,
65
+ @request.content_type,
66
+ @request.content_hash,
67
+ parse_uri(@request.original_uri || @request.request_uri),
68
+ @request.timestamp]
68
69
 
69
- if request_method.nil?
70
- raise ArgumentError, "unable to determine the http method from the request, please supply an override"
70
+ if headers_to_sign.is_a?(Array) && headers_to_sign.any?
71
+ headers_to_sign.each { |h| canonical_array << headers[h] if headers[h].present? }
71
72
  end
72
73
 
73
- [ request_method.upcase,
74
- @request.content_type,
75
- @request.content_md5,
76
- parse_uri(@request.request_uri),
77
- @request.timestamp
78
- ].join(",")
74
+ canonical_array.join(',')
79
75
  end
80
76
 
81
77
  # Returns the authorization header from the request's headers
@@ -84,18 +80,18 @@ module ApiAuth
84
80
  end
85
81
 
86
82
  def set_date
87
- @request.set_date if @request.timestamp.empty?
83
+ @request.set_date if @request.timestamp.nil?
88
84
  end
89
85
 
90
- def calculate_md5
91
- @request.populate_content_md5 if @request.content_md5.empty?
86
+ def calculate_hash
87
+ @request.populate_content_hash if @request.content_hash.nil?
92
88
  end
93
89
 
94
- def md5_mismatch?
95
- if @request.content_md5.empty?
90
+ def content_hash_mismatch?
91
+ if @request.content_hash.nil?
96
92
  false
97
93
  else
98
- @request.md5_mismatch?
94
+ @request.content_hash_mismatch?
99
95
  end
100
96
  end
101
97
 
@@ -110,12 +106,12 @@ module ApiAuth
110
106
 
111
107
  private
112
108
 
113
- URI_WITHOUT_HOST_REGEXP = %r{https?://[^,?/]*}
114
-
115
109
  def parse_uri(uri)
116
- uri_without_host = uri.gsub(URI_WITHOUT_HOST_REGEXP, '')
117
- return '/' if uri_without_host.empty?
118
- uri_without_host
110
+ parsed_uri = URI.parse(uri)
111
+
112
+ return parsed_uri.request_uri if parsed_uri.respond_to?(:request_uri)
113
+
114
+ uri.empty? ? '/' : uri
119
115
  end
120
116
  end
121
117
  end
@@ -1,31 +1,22 @@
1
1
  module ApiAuth
2
-
3
2
  module Helpers # :nodoc:
4
-
5
3
  def b64_encode(string)
6
- if Base64.respond_to?(:strict_encode64)
7
- Base64.strict_encode64(string)
8
- else
9
- # Fall back to stripping out newlines on Ruby 1.8.
10
- Base64.encode64(string).gsub(/\n/, '')
11
- end
4
+ Base64.strict_encode64(string)
5
+ end
6
+
7
+ def sha256_base64digest(string)
8
+ Digest::SHA256.base64digest(string)
12
9
  end
13
10
 
14
11
  def md5_base64digest(string)
15
- if Digest::MD5.respond_to?(:base64digest)
16
- Digest::MD5.base64digest(string)
17
- else
18
- b64_encode(Digest::MD5.digest(string))
19
- end
12
+ Digest::MD5.base64digest(string)
20
13
  end
21
14
 
22
15
  # Capitalizes the keys of a hash
23
16
  def capitalize_keys(hsh)
24
17
  capitalized_hash = {}
25
- hsh.each_pair {|k,v| capitalized_hash[k.to_s.upcase] = v }
18
+ hsh.each_pair { |k, v| capitalized_hash[k.to_s.upcase] = v }
26
19
  capitalized_hash
27
20
  end
28
-
29
21
  end
30
-
31
22
  end
@@ -1,13 +1,9 @@
1
1
  module ApiAuth
2
-
3
2
  # Integration with Rails
4
3
  #
5
4
  class Rails # :nodoc:
6
-
7
5
  module ControllerMethods # :nodoc:
8
-
9
6
  module InstanceMethods # :nodoc:
10
-
11
7
  def get_api_access_id_from_request
12
8
  ApiAuth.access_id(request)
13
9
  end
@@ -15,85 +11,59 @@ module ApiAuth
15
11
  def api_authenticated?(secret_key)
16
12
  ApiAuth.authentic?(request, secret_key)
17
13
  end
18
-
19
14
  end
20
15
 
21
- unless defined?(ActionController)
22
- begin
23
- require 'rubygems'
24
- gem 'actionpack'
25
- gem 'activesupport'
26
- require 'action_controller'
27
- require 'active_support'
28
- rescue LoadError
29
- nil
16
+ if defined?(ActiveSupport)
17
+ ActiveSupport.on_load(:action_controller) do
18
+ ActionController::Base.include(ControllerMethods::InstanceMethods)
30
19
  end
31
20
  end
21
+ end
32
22
 
33
- if defined?(ActionController::Base)
34
- ActionController::Base.send(:include, ControllerMethods::InstanceMethods)
35
- end
36
-
37
- end # ControllerMethods
38
-
39
- module ActiveResourceExtension # :nodoc:
40
-
23
+ module ActiveResourceExtension # :nodoc:
41
24
  module ActiveResourceApiAuth # :nodoc:
42
-
43
25
  def self.included(base)
44
26
  base.extend(ClassMethods)
45
-
46
- if base.respond_to?('class_attribute')
47
- base.class_attribute :hmac_access_id
48
- base.class_attribute :hmac_secret_key
49
- base.class_attribute :use_hmac
50
- base.class_attribute :sign_with_http_method
51
- else
52
- base.class_inheritable_accessor :hmac_access_id
53
- base.class_inheritable_accessor :hmac_secret_key
54
- base.class_inheritable_accessor :use_hmac
55
- base.class_inheritable_accessor :sign_with_http_method
56
- end
57
-
27
+ base.class_attribute :hmac_access_id
28
+ base.class_attribute :hmac_secret_key
29
+ base.class_attribute :use_hmac
30
+ base.class_attribute :api_auth_options
58
31
  end
59
32
 
60
33
  module ClassMethods
61
-
62
34
  def with_api_auth(access_id, secret_key, options = {})
63
- sign_with_http_method = options[:sign_with_http_method] || false
64
-
65
35
  self.hmac_access_id = access_id
66
36
  self.hmac_secret_key = secret_key
67
- self.sign_with_http_method = sign_with_http_method
68
37
  self.use_hmac = true
38
+ self.api_auth_options = options
69
39
 
70
40
  class << self
71
- alias_method_chain :connection, :auth
41
+ alias_method :connection_without_auth, :connection
42
+ alias_method :connection, :connection_with_auth
72
43
  end
73
44
  end
74
45
 
75
46
  def connection_with_auth(refresh = false)
76
47
  c = connection_without_auth(refresh)
77
- c.hmac_access_id = self.hmac_access_id
78
- c.hmac_secret_key = self.hmac_secret_key
79
- c.use_hmac = self.use_hmac
80
- c.sign_with_http_method = self.sign_with_http_method
48
+ c.hmac_access_id = hmac_access_id
49
+ c.hmac_secret_key = hmac_secret_key
50
+ c.use_hmac = use_hmac
51
+ c.api_auth_options = api_auth_options
81
52
  c
82
53
  end
83
-
84
- end # class methods
54
+ end
85
55
 
86
56
  module InstanceMethods
87
57
  end
88
-
89
- end # BaseApiAuth
58
+ end
90
59
 
91
60
  module Connection
92
-
93
61
  def self.included(base)
94
- base.send :alias_method_chain, :request, :auth
62
+ base.send :alias_method, :request_without_auth, :request
63
+ base.send :alias_method, :request, :request_with_auth
64
+
95
65
  base.class_eval do
96
- attr_accessor :hmac_secret_key, :hmac_access_id, :use_hmac, :sign_with_http_method
66
+ attr_accessor :hmac_secret_key, :hmac_access_id, :use_hmac, :api_auth_options
97
67
  end
98
68
  end
99
69
 
@@ -102,34 +72,24 @@ module ApiAuth
102
72
  h = arguments.last
103
73
  tmp = "Net::HTTP::#{method.to_s.capitalize}".constantize.new(path, h)
104
74
  tmp.body = arguments[0] if arguments.length > 1
105
- ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key, {:with_http_method => (sign_with_http_method || false)})
106
- arguments.last['Content-MD5'] = tmp['Content-MD5'] if tmp['Content-MD5']
75
+ ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key, api_auth_options)
76
+ if tmp['X-Authorization-Content-SHA256']
77
+ arguments.last['X-Authorization-Content-SHA256'] = tmp['X-Authorization-Content-SHA256']
78
+ end
107
79
  arguments.last['DATE'] = tmp['DATE']
108
80
  arguments.last['Authorization'] = tmp['Authorization']
109
81
  end
110
82
 
111
83
  request_without_auth(method, path, *arguments)
112
84
  end
113
-
114
- end # Connection
115
-
116
- unless defined?(ActiveResource)
117
- begin
118
- require 'rubygems'
119
- gem 'activeresource'
120
- require 'active_resource'
121
- rescue LoadError
122
- nil
123
- end
124
85
  end
125
86
 
126
- if defined?(ActiveResource)
127
- ActiveResource::Base.send(:include, ActiveResourceApiAuth)
128
- ActiveResource::Connection.send(:include, Connection)
87
+ if defined?(ActiveSupport)
88
+ ActiveSupport.on_load(:active_resource) do
89
+ ActiveResource::Base.include(ActiveResourceApiAuth)
90
+ ActiveResource::Connection.include(Connection)
91
+ end
129
92
  end
130
-
131
- end # ActiveResourceExtension
132
-
133
- end # Rails
134
-
135
- end # ApiAuth
93
+ end
94
+ end
95
+ end
@@ -1,38 +1,38 @@
1
1
  module ApiAuth
2
-
3
2
  module RequestDrivers # :nodoc:
4
-
5
3
  class ActionControllerRequest # :nodoc:
6
-
7
4
  include ApiAuth::Helpers
8
5
 
9
- def initialize(request)
6
+ def initialize(request, authorize_md5: false)
10
7
  @request = request
8
+ @authorize_md5 = authorize_md5
11
9
  fetch_headers
12
10
  true
13
11
  end
14
12
 
15
13
  def set_auth_header(header)
16
- @request.env["Authorization"] = header
14
+ @request.env['Authorization'] = header
17
15
  fetch_headers
18
16
  @request
19
17
  end
20
18
 
21
- def calculated_md5
19
+ def calculated_hash
22
20
  body = @request.raw_post
23
- md5_base64digest(body)
21
+ hashes = [sha256_base64digest(body)]
22
+ hashes << md5_base64digest(body) if @authorize_md5
23
+ hashes
24
24
  end
25
25
 
26
- def populate_content_md5
27
- if @request.put? || @request.post?
28
- @request.env["Content-MD5"] = calculated_md5
29
- fetch_headers
30
- end
26
+ def populate_content_hash
27
+ return unless @request.put? || @request.post?
28
+
29
+ @request.env['X-AUTHORIZATION-CONTENT-SHA256'] = calculated_hash
30
+ fetch_headers
31
31
  end
32
32
 
33
- def md5_mismatch?
33
+ def content_hash_mismatch?
34
34
  if @request.put? || @request.post?
35
- calculated_md5 != content_md5
35
+ !calculated_hash.include?(content_hash)
36
36
  else
37
37
  false
38
38
  end
@@ -47,13 +47,17 @@ module ApiAuth
47
47
  end
48
48
 
49
49
  def content_type
50
- value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
51
- value.nil? ? "" : value
50
+ find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
51
+ end
52
+
53
+ def content_hash
54
+ headers = %w[X-AUTHORIZATION-CONTENT-SHA256 X_AUTHORIZATION_CONTENT_SHA256 HTTP_X_AUTHORIZATION_CONTENT_SHA256]
55
+ headers += %w[CONTENT-MD5 CONTENT_MD5 HTTP_CONTENT_MD5] if @authorize_md5
56
+ find_header(headers)
52
57
  end
53
58
 
54
- def content_md5
55
- value = find_header(%w(CONTENT-MD5 CONTENT_MD5 HTTP_CONTENT_MD5))
56
- value.nil? ? "" : value
59
+ def original_uri
60
+ find_header(%w[X-ORIGINAL-URI X_ORIGINAL_URI HTTP_X_ORIGINAL_URI])
57
61
  end
58
62
 
59
63
  def request_uri
@@ -66,22 +70,18 @@ module ApiAuth
66
70
  end
67
71
 
68
72
  def timestamp
69
- value = find_header(%w(DATE HTTP_DATE))
70
- value.nil? ? "" : value
73
+ find_header(%w[DATE HTTP_DATE])
71
74
  end
72
75
 
73
76
  def authorization_header
74
- find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
77
+ find_header %w[Authorization AUTHORIZATION HTTP_AUTHORIZATION]
75
78
  end
76
79
 
77
- private
80
+ private
78
81
 
79
82
  def find_header(keys)
80
- keys.map {|key| @headers[key] }.compact.first
83
+ keys.map { |key| @headers[key] }.compact.first
81
84
  end
82
-
83
85
  end
84
-
85
86
  end
86
-
87
87
  end
@@ -1,15 +1,9 @@
1
1
  module ApiAuth
2
-
3
2
  module RequestDrivers # :nodoc:
4
-
5
3
  class ActionDispatchRequest < ActionControllerRequest # :nodoc:
6
-
7
4
  def request_uri
8
5
  @request.fullpath
9
6
  end
10
-
11
7
  end
12
-
13
8
  end
14
-
15
9
  end
@@ -1,9 +1,6 @@
1
1
  module ApiAuth
2
-
3
2
  module RequestDrivers # :nodoc:
4
-
5
3
  class CurbRequest # :nodoc:
6
-
7
4
  include ApiAuth::Helpers
8
5
 
9
6
  def initialize(request)
@@ -13,16 +10,16 @@ module ApiAuth
13
10
  end
14
11
 
15
12
  def set_auth_header(header)
16
- @request.headers.merge!({ "Authorization" => header })
13
+ @request.headers['Authorization'] = header
17
14
  fetch_headers
18
15
  @request
19
16
  end
20
17
 
21
- def populate_content_md5
22
- nil #doesn't appear to be possible
18
+ def populate_content_hash
19
+ nil # doesn't appear to be possible
23
20
  end
24
21
 
25
- def md5_mismatch?
22
+ def content_hash_mismatch?
26
23
  false
27
24
  end
28
25
 
@@ -35,13 +32,15 @@ module ApiAuth
35
32
  end
36
33
 
37
34
  def content_type
38
- value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
39
- value.nil? ? "" : value
35
+ find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
36
+ end
37
+
38
+ def content_hash
39
+ find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
40
40
  end
41
41
 
42
- def content_md5
43
- value = find_header(%w(CONTENT-MD5 CONTENT_MD5))
44
- value.nil? ? "" : value
42
+ def original_uri
43
+ find_header(%w[X-ORIGINAL-URI X_ORIGINAL_URI HTTP_X_ORIGINAL_URI])
45
44
  end
46
45
 
47
46
  def request_uri
@@ -49,27 +48,23 @@ module ApiAuth
49
48
  end
50
49
 
51
50
  def set_date
52
- @request.headers.merge!({ "DATE" => Time.now.utc.httpdate })
51
+ @request.headers['DATE'] = Time.now.utc.httpdate
53
52
  fetch_headers
54
53
  end
55
54
 
56
55
  def timestamp
57
- value = find_header(%w(DATE HTTP_DATE))
58
- value.nil? ? "" : value
56
+ find_header(%w[DATE HTTP_DATE])
59
57
  end
60
58
 
61
59
  def authorization_header
62
- find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
60
+ find_header %w[Authorization AUTHORIZATION HTTP_AUTHORIZATION]
63
61
  end
64
62
 
65
- private
63
+ private
66
64
 
67
65
  def find_header(keys)
68
- keys.map {|key| @headers[key] }.compact.first
66
+ keys.map { |key| @headers[key] }.compact.first
69
67
  end
70
-
71
68
  end
72
-
73
69
  end
74
-
75
70
  end
@@ -1,9 +1,6 @@
1
1
  module ApiAuth
2
-
3
2
  module RequestDrivers # :nodoc:
4
-
5
3
  class FaradayRequest # :nodoc:
6
-
7
4
  include ApiAuth::Helpers
8
5
 
9
6
  def initialize(request)
@@ -13,30 +10,26 @@ module ApiAuth
13
10
  end
14
11
 
15
12
  def set_auth_header(header)
16
- @request.headers.merge!({ "Authorization" => header })
13
+ @request.headers['Authorization'] = header
17
14
  fetch_headers
18
15
  @request
19
16
  end
20
17
 
21
- def calculated_md5
22
- if @request.body
23
- body = @request.body
24
- else
25
- body = ''
26
- end
27
- md5_base64digest(body)
18
+ def calculated_hash
19
+ body = @request.body || ''
20
+ sha256_base64digest(body)
28
21
  end
29
22
 
30
- def populate_content_md5
31
- if ['POST', 'PUT'].include?(@request.method.to_s.upcase)
32
- @request.headers["Content-MD5"] = calculated_md5
33
- fetch_headers
34
- end
23
+ def populate_content_hash
24
+ return unless %w[POST PUT].include?(@request.http_method.to_s.upcase)
25
+
26
+ @request.headers['X-Authorization-Content-SHA256'] = calculated_hash
27
+ fetch_headers
35
28
  end
36
29
 
37
- def md5_mismatch?
38
- if ['POST', 'PUT'].include?(@request.method.to_s.upcase)
39
- calculated_md5 != content_md5
30
+ def content_hash_mismatch?
31
+ if %w[POST PUT].include?(@request.http_method.to_s.upcase)
32
+ calculated_hash != content_hash
40
33
  else
41
34
  false
42
35
  end
@@ -47,17 +40,19 @@ module ApiAuth
47
40
  end
48
41
 
49
42
  def http_method
50
- @request.method.to_s.upcase
43
+ @request.http_method.to_s.upcase
51
44
  end
52
45
 
53
46
  def content_type
54
- value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
55
- value.nil? ? "" : value
47
+ find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
48
+ end
49
+
50
+ def content_hash
51
+ find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
56
52
  end
57
53
 
58
- def content_md5
59
- value = find_header(%w(CONTENT-MD5 CONTENT_MD5 HTTP-CONTENT-MD5 HTTP_CONTENT_MD5))
60
- value.nil? ? "" : value
54
+ def original_uri
55
+ find_header(%w[X-ORIGINAL-URI X_ORIGINAL_URI HTTP_X_ORIGINAL_URI])
61
56
  end
62
57
 
63
58
  def request_uri
@@ -68,27 +63,23 @@ module ApiAuth
68
63
  end
69
64
 
70
65
  def set_date
71
- @request.headers.merge!({ "DATE" => Time.now.utc.httpdate })
66
+ @request.headers['DATE'] = Time.now.utc.httpdate
72
67
  fetch_headers
73
68
  end
74
69
 
75
70
  def timestamp
76
- value = find_header(%w(DATE HTTP_DATE))
77
- value.nil? ? "" : value
71
+ find_header(%w[DATE HTTP_DATE])
78
72
  end
79
73
 
80
74
  def authorization_header
81
- find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
75
+ find_header %w[Authorization AUTHORIZATION HTTP_AUTHORIZATION]
82
76
  end
83
77
 
84
- private
78
+ private
85
79
 
86
80
  def find_header(keys)
87
- keys.map {|key| @headers[key] }.compact.first
81
+ keys.map { |key| @headers[key] }.compact.first
88
82
  end
89
-
90
83
  end
91
-
92
84
  end
93
-
94
85
  end