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
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
module ApiAuth
|
|
2
|
+
module RequestDrivers # :nodoc:
|
|
3
|
+
# Internally, Faraday uses the class Faraday::Env to represent requests. The class is not meant
|
|
4
|
+
# to be directly exposed to users, but this is what Faraday middlewares work with. See
|
|
5
|
+
# <https://lostisland.github.io/faraday/middleware/>.
|
|
6
|
+
class FaradayEnv
|
|
7
|
+
include ApiAuth::Helpers
|
|
8
|
+
|
|
9
|
+
def initialize(env)
|
|
10
|
+
@env = env
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def set_auth_header(header)
|
|
14
|
+
@env.request_headers['Authorization'] = header
|
|
15
|
+
@env
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def calculated_hash
|
|
19
|
+
sha256_base64digest(body)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def populate_content_hash
|
|
23
|
+
return unless %w[POST PUT PATCH].include?(http_method)
|
|
24
|
+
|
|
25
|
+
@env.request_headers['X-Authorization-Content-SHA256'] = calculated_hash
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def content_hash_mismatch?
|
|
29
|
+
if %w[POST PUT PATCH].include?(http_method)
|
|
30
|
+
calculated_hash != content_hash
|
|
31
|
+
else
|
|
32
|
+
false
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def http_method
|
|
37
|
+
@env.method.to_s.upcase
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def content_type
|
|
41
|
+
type = find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
|
42
|
+
|
|
43
|
+
# When sending a body-less POST request, the Content-Type is set at the last minute by the
|
|
44
|
+
# Net::HTTP adapter, which states in the documentation for Net::HTTP#post:
|
|
45
|
+
#
|
|
46
|
+
# > You should set Content-Type: header field for POST. If no Content-Type: field given,
|
|
47
|
+
# > this method uses “application/x-www-form-urlencoded” by default.
|
|
48
|
+
#
|
|
49
|
+
# The same applies to PATCH and PUT. Hopefully the other HTTP adapters behave similarly.
|
|
50
|
+
#
|
|
51
|
+
type ||= 'application/x-www-form-urlencoded' if %w[POST PATCH PUT].include?(http_method)
|
|
52
|
+
|
|
53
|
+
type
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def content_hash
|
|
57
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def original_uri
|
|
61
|
+
find_header(%w[X-ORIGINAL-URI X_ORIGINAL_URI HTTP_X_ORIGINAL_URI])
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def request_uri
|
|
65
|
+
@env.url.request_uri
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def set_date
|
|
69
|
+
@env.request_headers['Date'] = Time.now.utc.httpdate
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def timestamp
|
|
73
|
+
find_header(%w[DATE HTTP_DATE])
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def authorization_header
|
|
77
|
+
find_header(%w[Authorization AUTHORIZATION HTTP_AUTHORIZATION])
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def body
|
|
81
|
+
body_source = @env.request_body
|
|
82
|
+
if body_source.respond_to?(:read)
|
|
83
|
+
result = body_source.read
|
|
84
|
+
body_source.rewind
|
|
85
|
+
result
|
|
86
|
+
else
|
|
87
|
+
body_source.to_s
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def fetch_headers
|
|
92
|
+
capitalize_keys @env.request_headers
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
def find_header(keys)
|
|
98
|
+
keys.map { |key| @env.request_headers[key] }.compact.first
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module ApiAuth
|
|
2
|
+
module RequestDrivers # :nodoc:
|
|
3
|
+
class GrapeRequest # :nodoc:
|
|
4
|
+
include ApiAuth::Helpers
|
|
5
|
+
|
|
6
|
+
def initialize(request)
|
|
7
|
+
@request = request
|
|
8
|
+
save_headers
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def set_auth_header(header)
|
|
13
|
+
@request.env['HTTP_AUTHORIZATION'] = header
|
|
14
|
+
save_headers # enforce update of processed_headers based on last updated headers
|
|
15
|
+
@request
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def calculated_hash
|
|
19
|
+
body = @request.body.read
|
|
20
|
+
@request.body.rewind
|
|
21
|
+
sha256_base64digest(body)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def populate_content_hash
|
|
25
|
+
return if !@request.put? && !@request.post?
|
|
26
|
+
|
|
27
|
+
@request.env['HTTP_X_AUTHORIZATION_CONTENT_SHA256'] = calculated_hash
|
|
28
|
+
save_headers
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def content_hash_mismatch?
|
|
32
|
+
if @request.put? || @request.post?
|
|
33
|
+
calculated_hash != content_hash
|
|
34
|
+
else
|
|
35
|
+
false
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def fetch_headers
|
|
40
|
+
capitalize_keys @request.env
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def http_method
|
|
44
|
+
@request.request_method.upcase
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def content_type
|
|
48
|
+
find_header %w[HTTP_X_HMAC_CONTENT_TYPE HTTP_X_CONTENT_TYPE CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def content_hash
|
|
52
|
+
find_header %w[HTTP_X_AUTHORIZATION_CONTENT_SHA256]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def original_uri
|
|
56
|
+
find_header %w[HTTP_X_HMAC_ORIGINAL_URI HTTP_X_ORIGINAL_URI X-ORIGINAL-URI X_ORIGINAL_URI]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def request_uri
|
|
60
|
+
@request.url
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def set_date
|
|
64
|
+
@request.env['HTTP_DATE'] = Time.now.utc.httpdate
|
|
65
|
+
save_headers
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def timestamp
|
|
69
|
+
find_header %w[HTTP_X_HMAC_DATE HTTP_X_DATE DATE HTTP_DATE]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def authorization_header
|
|
73
|
+
find_header %w[HTTP_X_HMAC_AUTHORIZATION HTTP_X_AUTHORIZATION Authorization AUTHORIZATION HTTP_AUTHORIZATION]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def find_header(keys)
|
|
79
|
+
keys.map { |key| @headers[key] }.compact.first
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def save_headers
|
|
83
|
+
@headers = fetch_headers
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module ApiAuth
|
|
2
|
+
module RequestDrivers # :nodoc:
|
|
3
|
+
class HttpRequest # :nodoc:
|
|
4
|
+
include ApiAuth::Helpers
|
|
5
|
+
|
|
6
|
+
def initialize(request)
|
|
7
|
+
@request = request
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def set_auth_header(header)
|
|
11
|
+
@request['Authorization'] = header
|
|
12
|
+
@request
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def calculated_hash
|
|
16
|
+
sha256_base64digest(body)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def populate_content_hash
|
|
20
|
+
return unless %w[POST PUT].include?(http_method)
|
|
21
|
+
|
|
22
|
+
@request['X-Authorization-Content-SHA256'] = calculated_hash
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def content_hash_mismatch?
|
|
26
|
+
if %w[POST PUT].include?(http_method)
|
|
27
|
+
calculated_hash != content_hash
|
|
28
|
+
else
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def http_method
|
|
34
|
+
@request.verb.to_s.upcase
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def content_type
|
|
38
|
+
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def content_hash
|
|
42
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def original_uri
|
|
46
|
+
find_header(%w[X-ORIGINAL-URI X_ORIGINAL_URI HTTP_X_ORIGINAL_URI])
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def request_uri
|
|
50
|
+
@request.uri.request_uri
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def set_date
|
|
54
|
+
@request['Date'] = Time.now.utc.httpdate
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def timestamp
|
|
58
|
+
find_header(%w[DATE HTTP_DATE])
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def authorization_header
|
|
62
|
+
find_header %w[Authorization AUTHORIZATION HTTP_AUTHORIZATION]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def body
|
|
66
|
+
if body_source.respond_to?(:read)
|
|
67
|
+
result = body_source.read
|
|
68
|
+
body_source.rewind
|
|
69
|
+
result
|
|
70
|
+
else
|
|
71
|
+
body_source.to_s
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def fetch_headers
|
|
76
|
+
capitalize_keys @request.headers.to_h
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def find_header(keys)
|
|
82
|
+
keys.map { |key| @request[key] }.compact.first
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def body_source
|
|
86
|
+
body = @request.body
|
|
87
|
+
|
|
88
|
+
if defined?(::HTTP::Request::Body)
|
|
89
|
+
body.respond_to?(:source) ? body.source : body.instance_variable_get(:@body)
|
|
90
|
+
else
|
|
91
|
+
body
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
module ApiAuth
|
|
2
|
-
|
|
3
2
|
module RequestDrivers # :nodoc:
|
|
4
|
-
|
|
5
3
|
class HttpiRequest # :nodoc:
|
|
6
|
-
|
|
7
4
|
include ApiAuth::Helpers
|
|
8
5
|
|
|
9
6
|
def initialize(request)
|
|
@@ -13,25 +10,25 @@ 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
|
-
|
|
18
|
+
def calculated_hash
|
|
19
|
+
sha256_base64digest(@request.body || '')
|
|
23
20
|
end
|
|
24
21
|
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
def populate_content_hash
|
|
23
|
+
return unless @request.body
|
|
24
|
+
|
|
25
|
+
@request.headers['X-Authorization-Content-SHA256'] = calculated_hash
|
|
26
|
+
fetch_headers
|
|
30
27
|
end
|
|
31
28
|
|
|
32
|
-
def
|
|
29
|
+
def content_hash_mismatch?
|
|
33
30
|
if @request.body
|
|
34
|
-
|
|
31
|
+
calculated_hash != content_hash
|
|
35
32
|
else
|
|
36
33
|
false
|
|
37
34
|
end
|
|
@@ -46,13 +43,15 @@ module ApiAuth
|
|
|
46
43
|
end
|
|
47
44
|
|
|
48
45
|
def content_type
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def content_hash
|
|
50
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
def
|
|
54
|
-
|
|
55
|
-
value.nil? ? "" : value
|
|
53
|
+
def original_uri
|
|
54
|
+
find_header(%w[X-ORIGINAL-URI X_ORIGINAL_URI HTTP_X_ORIGINAL_URI])
|
|
56
55
|
end
|
|
57
56
|
|
|
58
57
|
def request_uri
|
|
@@ -60,27 +59,23 @@ module ApiAuth
|
|
|
60
59
|
end
|
|
61
60
|
|
|
62
61
|
def set_date
|
|
63
|
-
@request.headers[
|
|
62
|
+
@request.headers['DATE'] = Time.now.utc.httpdate
|
|
64
63
|
fetch_headers
|
|
65
64
|
end
|
|
66
65
|
|
|
67
66
|
def timestamp
|
|
68
|
-
|
|
69
|
-
value.nil? ? "" : value
|
|
67
|
+
find_header(%w[DATE HTTP_DATE])
|
|
70
68
|
end
|
|
71
69
|
|
|
72
70
|
def authorization_header
|
|
73
|
-
find_header %w
|
|
71
|
+
find_header %w[Authorization AUTHORIZATION HTTP_AUTHORIZATION]
|
|
74
72
|
end
|
|
75
73
|
|
|
76
|
-
|
|
74
|
+
private
|
|
77
75
|
|
|
78
76
|
def find_header(keys)
|
|
79
|
-
keys.map {|key| @headers[key] }.compact.first
|
|
77
|
+
keys.map { |key| @headers[key] }.compact.first
|
|
80
78
|
end
|
|
81
|
-
|
|
82
79
|
end
|
|
83
|
-
|
|
84
80
|
end
|
|
85
|
-
|
|
86
81
|
end
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
module ApiAuth
|
|
2
|
-
|
|
3
2
|
module RequestDrivers # :nodoc:
|
|
4
|
-
|
|
5
3
|
class NetHttpRequest # :nodoc:
|
|
6
|
-
|
|
7
4
|
include ApiAuth::Helpers
|
|
8
5
|
|
|
9
6
|
def initialize(request)
|
|
@@ -13,12 +10,12 @@ module ApiAuth
|
|
|
13
10
|
end
|
|
14
11
|
|
|
15
12
|
def set_auth_header(header)
|
|
16
|
-
@request[
|
|
13
|
+
@request['Authorization'] = header
|
|
17
14
|
@headers = fetch_headers
|
|
18
15
|
@request
|
|
19
16
|
end
|
|
20
17
|
|
|
21
|
-
def
|
|
18
|
+
def calculated_hash
|
|
22
19
|
if @request.respond_to?(:body_stream) && @request.body_stream
|
|
23
20
|
body = @request.body_stream.read
|
|
24
21
|
@request.body_stream.rewind
|
|
@@ -26,18 +23,18 @@ module ApiAuth
|
|
|
26
23
|
body = @request.body
|
|
27
24
|
end
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
sha256_base64digest(body || '')
|
|
30
27
|
end
|
|
31
28
|
|
|
32
|
-
def
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
def populate_content_hash
|
|
30
|
+
return unless @request.class::REQUEST_HAS_BODY
|
|
31
|
+
|
|
32
|
+
@request['X-Authorization-Content-SHA256'] = calculated_hash
|
|
36
33
|
end
|
|
37
34
|
|
|
38
|
-
def
|
|
35
|
+
def content_hash_mismatch?
|
|
39
36
|
if @request.class::REQUEST_HAS_BODY
|
|
40
|
-
|
|
37
|
+
calculated_hash != content_hash
|
|
41
38
|
else
|
|
42
39
|
false
|
|
43
40
|
end
|
|
@@ -52,13 +49,15 @@ module ApiAuth
|
|
|
52
49
|
end
|
|
53
50
|
|
|
54
51
|
def content_type
|
|
55
|
-
|
|
56
|
-
value.nil? ? "" : value
|
|
52
|
+
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
|
57
53
|
end
|
|
58
54
|
|
|
59
|
-
def
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
def content_hash
|
|
56
|
+
find_header(%w[X-Authorization-Content-SHA256])
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def original_uri
|
|
60
|
+
find_header(%w[X-ORIGINAL-URI X_ORIGINAL_URI HTTP_X_ORIGINAL_URI])
|
|
62
61
|
end
|
|
63
62
|
|
|
64
63
|
def request_uri
|
|
@@ -66,26 +65,22 @@ module ApiAuth
|
|
|
66
65
|
end
|
|
67
66
|
|
|
68
67
|
def set_date
|
|
69
|
-
@request[
|
|
68
|
+
@request['DATE'] = Time.now.utc.httpdate
|
|
70
69
|
end
|
|
71
70
|
|
|
72
71
|
def timestamp
|
|
73
|
-
|
|
74
|
-
value.nil? ? "" : value
|
|
72
|
+
find_header(%w[DATE HTTP_DATE])
|
|
75
73
|
end
|
|
76
74
|
|
|
77
75
|
def authorization_header
|
|
78
|
-
find_header %w
|
|
76
|
+
find_header %w[Authorization AUTHORIZATION HTTP_AUTHORIZATION]
|
|
79
77
|
end
|
|
80
78
|
|
|
81
|
-
|
|
79
|
+
private
|
|
82
80
|
|
|
83
81
|
def find_header(keys)
|
|
84
|
-
keys.map {|key| @headers[key] }.compact.first
|
|
82
|
+
keys.map { |key| @headers[key] }.compact.first
|
|
85
83
|
end
|
|
86
|
-
|
|
87
84
|
end
|
|
88
|
-
|
|
89
85
|
end
|
|
90
|
-
|
|
91
86
|
end
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
module ApiAuth
|
|
2
|
-
|
|
3
2
|
module RequestDrivers # :nodoc:
|
|
4
|
-
|
|
5
3
|
class RackRequest # :nodoc:
|
|
6
|
-
|
|
7
4
|
include ApiAuth::Helpers
|
|
8
5
|
|
|
9
6
|
def initialize(request)
|
|
@@ -13,31 +10,31 @@ module ApiAuth
|
|
|
13
10
|
end
|
|
14
11
|
|
|
15
12
|
def set_auth_header(header)
|
|
16
|
-
@request.env
|
|
13
|
+
@request.env['Authorization'] = header
|
|
17
14
|
fetch_headers
|
|
18
15
|
@request
|
|
19
16
|
end
|
|
20
17
|
|
|
21
|
-
def
|
|
18
|
+
def calculated_hash
|
|
22
19
|
if @request.body
|
|
23
20
|
body = @request.body.read
|
|
24
21
|
@request.body.rewind
|
|
25
22
|
else
|
|
26
23
|
body = ''
|
|
27
24
|
end
|
|
28
|
-
|
|
25
|
+
sha256_base64digest(body)
|
|
29
26
|
end
|
|
30
27
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
def populate_content_hash
|
|
29
|
+
return unless %w[POST PUT].include?(@request.request_method)
|
|
30
|
+
|
|
31
|
+
@request.env['X-Authorization-Content-SHA256'] = calculated_hash
|
|
32
|
+
fetch_headers
|
|
36
33
|
end
|
|
37
34
|
|
|
38
|
-
def
|
|
39
|
-
if [
|
|
40
|
-
|
|
35
|
+
def content_hash_mismatch?
|
|
36
|
+
if %w[POST PUT].include?(@request.request_method)
|
|
37
|
+
calculated_hash != content_hash
|
|
41
38
|
else
|
|
42
39
|
false
|
|
43
40
|
end
|
|
@@ -52,13 +49,15 @@ module ApiAuth
|
|
|
52
49
|
end
|
|
53
50
|
|
|
54
51
|
def content_type
|
|
55
|
-
|
|
56
|
-
value.nil? ? "" : value
|
|
52
|
+
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
|
57
53
|
end
|
|
58
54
|
|
|
59
|
-
def
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
def content_hash
|
|
56
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def original_uri
|
|
60
|
+
find_header(%w[X-ORIGINAL-URI X_ORIGINAL_URI HTTP_X_ORIGINAL_URI])
|
|
62
61
|
end
|
|
63
62
|
|
|
64
63
|
def request_uri
|
|
@@ -66,27 +65,23 @@ module ApiAuth
|
|
|
66
65
|
end
|
|
67
66
|
|
|
68
67
|
def set_date
|
|
69
|
-
@request.env
|
|
68
|
+
@request.env['DATE'] = Time.now.utc.httpdate
|
|
70
69
|
fetch_headers
|
|
71
70
|
end
|
|
72
71
|
|
|
73
72
|
def timestamp
|
|
74
|
-
|
|
75
|
-
value.nil? ? "" : value
|
|
73
|
+
find_header(%w[DATE HTTP_DATE])
|
|
76
74
|
end
|
|
77
75
|
|
|
78
76
|
def authorization_header
|
|
79
|
-
find_header %w
|
|
77
|
+
find_header %w[Authorization AUTHORIZATION HTTP_AUTHORIZATION]
|
|
80
78
|
end
|
|
81
79
|
|
|
82
|
-
|
|
80
|
+
private
|
|
83
81
|
|
|
84
82
|
def find_header(keys)
|
|
85
|
-
keys.map {|key| @headers[key] }.compact.first
|
|
83
|
+
keys.map { |key| @headers[key] }.compact.first
|
|
86
84
|
end
|
|
87
|
-
|
|
88
85
|
end
|
|
89
|
-
|
|
90
86
|
end
|
|
91
|
-
|
|
92
87
|
end
|