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.
- checksums.yaml +5 -5
- data/.github/workflows/main.yml +71 -0
- data/.gitignore +13 -44
- data/.rubocop.yml +39 -0
- data/.rubocop_todo.yml +83 -0
- data/Appraisals +12 -36
- data/CHANGELOG.md +75 -1
- data/README.md +155 -52
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/api_auth.gemspec +35 -23
- data/gemfiles/rails_60.gemfile +9 -0
- data/gemfiles/rails_61.gemfile +9 -0
- data/gemfiles/rails_70.gemfile +9 -0
- data/lib/api-auth.rb +1 -1
- data/lib/api_auth/base.rb +41 -35
- data/lib/api_auth/errors.rb +4 -3
- data/lib/api_auth/headers.rb +38 -42
- data/lib/api_auth/helpers.rb +7 -16
- data/lib/api_auth/railtie.rb +34 -74
- data/lib/api_auth/request_drivers/action_controller.rb +27 -27
- data/lib/api_auth/request_drivers/action_dispatch.rb +0 -6
- data/lib/api_auth/request_drivers/curb.rb +16 -21
- data/lib/api_auth/request_drivers/faraday.rb +25 -34
- data/lib/api_auth/request_drivers/faraday_env.rb +102 -0
- data/lib/api_auth/request_drivers/grape_request.rb +87 -0
- data/lib/api_auth/request_drivers/http.rb +96 -0
- data/lib/api_auth/request_drivers/httpi.rb +22 -27
- data/lib/api_auth/request_drivers/net_http.rb +21 -26
- data/lib/api_auth/request_drivers/rack.rb +23 -28
- data/lib/api_auth/request_drivers/rest_client.rb +24 -29
- data/lib/api_auth.rb +4 -0
- data/lib/faraday/api_auth/middleware.rb +35 -0
- data/lib/faraday/api_auth.rb +8 -0
- data/spec/api_auth_spec.rb +135 -96
- data/spec/faraday_middleware_spec.rb +17 -0
- data/spec/headers_spec.rb +148 -108
- data/spec/helpers_spec.rb +8 -10
- data/spec/railtie_spec.rb +80 -99
- data/spec/request_drivers/action_controller_spec.rb +122 -79
- data/spec/request_drivers/action_dispatch_spec.rb +212 -85
- data/spec/request_drivers/curb_spec.rb +36 -33
- data/spec/request_drivers/faraday_env_spec.rb +188 -0
- data/spec/request_drivers/faraday_spec.rb +87 -83
- data/spec/request_drivers/grape_request_spec.rb +280 -0
- data/spec/request_drivers/http_spec.rb +190 -0
- data/spec/request_drivers/httpi_spec.rb +59 -59
- data/spec/request_drivers/net_http_spec.rb +70 -66
- data/spec/request_drivers/rack_spec.rb +101 -97
- data/spec/request_drivers/rest_client_spec.rb +218 -144
- data/spec/spec_helper.rb +15 -12
- metadata +144 -83
- data/.travis.yml +0 -40
- data/Gemfile.lock +0 -115
- data/gemfiles/rails_23.gemfile +0 -9
- data/gemfiles/rails_23.gemfile.lock +0 -70
- data/gemfiles/rails_30.gemfile +0 -9
- data/gemfiles/rails_30.gemfile.lock +0 -92
- data/gemfiles/rails_31.gemfile +0 -9
- data/gemfiles/rails_31.gemfile.lock +0 -98
- data/gemfiles/rails_32.gemfile +0 -9
- data/gemfiles/rails_32.gemfile.lock +0 -97
- data/gemfiles/rails_4.gemfile +0 -9
- data/gemfiles/rails_4.gemfile.lock +0 -94
- data/gemfiles/rails_41.gemfile +0 -9
- data/gemfiles/rails_41.gemfile.lock +0 -98
- data/gemfiles/rails_42.gemfile +0 -9
- data/gemfiles/rails_42.gemfile.lock +0 -115
data/lib/api_auth/headers.rb
CHANGED
|
@@ -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
|
-
|
|
40
|
-
|
|
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.
|
|
45
|
-
|
|
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
|
-
|
|
54
|
+
@request.timestamp
|
|
52
55
|
end
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
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
|
-
|
|
67
|
-
|
|
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
|
|
70
|
-
|
|
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
|
-
|
|
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.
|
|
83
|
+
@request.set_date if @request.timestamp.nil?
|
|
88
84
|
end
|
|
89
85
|
|
|
90
|
-
def
|
|
91
|
-
@request.
|
|
86
|
+
def calculate_hash
|
|
87
|
+
@request.populate_content_hash if @request.content_hash.nil?
|
|
92
88
|
end
|
|
93
89
|
|
|
94
|
-
def
|
|
95
|
-
if @request.
|
|
90
|
+
def content_hash_mismatch?
|
|
91
|
+
if @request.content_hash.nil?
|
|
96
92
|
false
|
|
97
93
|
else
|
|
98
|
-
@request.
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
data/lib/api_auth/helpers.rb
CHANGED
|
@@ -1,31 +1,22 @@
|
|
|
1
1
|
module ApiAuth
|
|
2
|
-
|
|
3
2
|
module Helpers # :nodoc:
|
|
4
|
-
|
|
5
3
|
def b64_encode(string)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
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
|
data/lib/api_auth/railtie.rb
CHANGED
|
@@ -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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
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 =
|
|
78
|
-
c.hmac_secret_key =
|
|
79
|
-
c.use_hmac =
|
|
80
|
-
c.
|
|
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 :
|
|
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, :
|
|
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,
|
|
106
|
-
|
|
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?(
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
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[
|
|
14
|
+
@request.env['Authorization'] = header
|
|
17
15
|
fetch_headers
|
|
18
16
|
@request
|
|
19
17
|
end
|
|
20
18
|
|
|
21
|
-
def
|
|
19
|
+
def calculated_hash
|
|
22
20
|
body = @request.raw_post
|
|
23
|
-
|
|
21
|
+
hashes = [sha256_base64digest(body)]
|
|
22
|
+
hashes << md5_base64digest(body) if @authorize_md5
|
|
23
|
+
hashes
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
|
33
|
+
def content_hash_mismatch?
|
|
34
34
|
if @request.put? || @request.post?
|
|
35
|
-
|
|
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
|
-
|
|
51
|
-
|
|
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
|
|
55
|
-
|
|
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
|
-
|
|
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
|
|
77
|
+
find_header %w[Authorization AUTHORIZATION HTTP_AUTHORIZATION]
|
|
75
78
|
end
|
|
76
79
|
|
|
77
|
-
|
|
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,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
|
|
13
|
+
@request.headers['Authorization'] = header
|
|
17
14
|
fetch_headers
|
|
18
15
|
@request
|
|
19
16
|
end
|
|
20
17
|
|
|
21
|
-
def
|
|
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
|
|
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
|
-
|
|
39
|
-
|
|
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
|
|
43
|
-
|
|
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
|
|
51
|
+
@request.headers['DATE'] = Time.now.utc.httpdate
|
|
53
52
|
fetch_headers
|
|
54
53
|
end
|
|
55
54
|
|
|
56
55
|
def timestamp
|
|
57
|
-
|
|
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
|
|
60
|
+
find_header %w[Authorization AUTHORIZATION HTTP_AUTHORIZATION]
|
|
63
61
|
end
|
|
64
62
|
|
|
65
|
-
|
|
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
|
|
13
|
+
@request.headers['Authorization'] = header
|
|
17
14
|
fetch_headers
|
|
18
15
|
@request
|
|
19
16
|
end
|
|
20
17
|
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
|
38
|
-
if [
|
|
39
|
-
|
|
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.
|
|
43
|
+
@request.http_method.to_s.upcase
|
|
51
44
|
end
|
|
52
45
|
|
|
53
46
|
def content_type
|
|
54
|
-
|
|
55
|
-
|
|
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
|
|
59
|
-
|
|
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
|
|
66
|
+
@request.headers['DATE'] = Time.now.utc.httpdate
|
|
72
67
|
fetch_headers
|
|
73
68
|
end
|
|
74
69
|
|
|
75
70
|
def timestamp
|
|
76
|
-
|
|
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
|
|
75
|
+
find_header %w[Authorization AUTHORIZATION HTTP_AUTHORIZATION]
|
|
82
76
|
end
|
|
83
77
|
|
|
84
|
-
|
|
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
|