api-auth 2.4.1 → 2.5.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 +4 -4
- data/.rubocop.yml +6 -2
- data/.rubocop_todo.yml +29 -19
- data/.travis.yml +4 -11
- data/CHANGELOG.md +8 -0
- data/README.md +28 -26
- data/VERSION +1 -1
- data/api_auth.gemspec +5 -4
- data/gemfiles/rails_60.gemfile +0 -2
- data/gemfiles/{rails_51.gemfile → rails_61.gemfile} +4 -2
- data/lib/api_auth/base.rb +2 -2
- data/lib/api_auth/headers.rb +6 -6
- data/lib/api_auth/helpers.rb +2 -2
- data/lib/api_auth/railtie.rb +3 -1
- data/lib/api_auth/request_drivers/action_controller.rb +8 -8
- data/lib/api_auth/request_drivers/curb.rb +4 -4
- data/lib/api_auth/request_drivers/faraday.rb +11 -11
- data/lib/api_auth/request_drivers/grape_request.rb +8 -8
- data/lib/api_auth/request_drivers/http.rb +8 -8
- data/lib/api_auth/request_drivers/httpi.rb +8 -8
- data/lib/api_auth/request_drivers/net_http.rb +8 -8
- data/lib/api_auth/request_drivers/rack.rb +8 -8
- data/lib/api_auth/request_drivers/rest_client.rb +8 -8
- data/spec/api_auth_spec.rb +8 -8
- data/spec/headers_spec.rb +26 -26
- data/spec/helpers_spec.rb +1 -1
- data/spec/railtie_spec.rb +3 -3
- data/spec/request_drivers/action_controller_spec.rb +35 -35
- data/spec/request_drivers/action_dispatch_spec.rb +35 -35
- data/spec/request_drivers/curb_spec.rb +8 -8
- data/spec/request_drivers/faraday_spec.rb +43 -43
- data/spec/request_drivers/grape_request_spec.rb +33 -32
- data/spec/request_drivers/http_spec.rb +23 -23
- data/spec/request_drivers/httpi_spec.rb +22 -22
- data/spec/request_drivers/net_http_spec.rb +23 -23
- data/spec/request_drivers/rack_spec.rb +35 -35
- data/spec/request_drivers/rest_client_spec.rb +36 -36
- metadata +29 -19
- data/gemfiles/http2.gemfile +0 -7
- data/gemfiles/http3.gemfile +0 -7
- data/gemfiles/rails_5.gemfile +0 -9
- data/spec/.rubocop.yml +0 -5
data/lib/api_auth/headers.rb
CHANGED
@@ -61,7 +61,7 @@ module ApiAuth
|
|
61
61
|
|
62
62
|
canonical_array = [request_method.upcase,
|
63
63
|
@request.content_type,
|
64
|
-
@request.
|
64
|
+
@request.content_hash,
|
65
65
|
parse_uri(@request.original_uri || @request.request_uri),
|
66
66
|
@request.timestamp]
|
67
67
|
|
@@ -81,15 +81,15 @@ module ApiAuth
|
|
81
81
|
@request.set_date if @request.timestamp.nil?
|
82
82
|
end
|
83
83
|
|
84
|
-
def
|
85
|
-
@request.
|
84
|
+
def calculate_hash
|
85
|
+
@request.populate_content_hash if @request.content_hash.nil?
|
86
86
|
end
|
87
87
|
|
88
|
-
def
|
89
|
-
if @request.
|
88
|
+
def content_hash_mismatch?
|
89
|
+
if @request.content_hash.nil?
|
90
90
|
false
|
91
91
|
else
|
92
|
-
@request.
|
92
|
+
@request.content_hash_mismatch?
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
data/lib/api_auth/helpers.rb
CHANGED
data/lib/api_auth/railtie.rb
CHANGED
@@ -73,7 +73,9 @@ module ApiAuth
|
|
73
73
|
tmp = "Net::HTTP::#{method.to_s.capitalize}".constantize.new(path, h)
|
74
74
|
tmp.body = arguments[0] if arguments.length > 1
|
75
75
|
ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key, api_auth_options)
|
76
|
-
|
76
|
+
if tmp['X-Authorization-Content-SHA256']
|
77
|
+
arguments.last['X-Authorization-Content-SHA256'] = tmp['X-Authorization-Content-SHA256']
|
78
|
+
end
|
77
79
|
arguments.last['DATE'] = tmp['DATE']
|
78
80
|
arguments.last['Authorization'] = tmp['Authorization']
|
79
81
|
end
|
@@ -15,21 +15,21 @@ module ApiAuth
|
|
15
15
|
@request
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def calculated_hash
|
19
19
|
body = @request.raw_post
|
20
|
-
|
20
|
+
sha256_base64digest(body)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
23
|
+
def populate_content_hash
|
24
24
|
return unless @request.put? || @request.post?
|
25
25
|
|
26
|
-
@request.env['
|
26
|
+
@request.env['X-AUTHORIZATION-CONTENT-SHA256'] = calculated_hash
|
27
27
|
fetch_headers
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
30
|
+
def content_hash_mismatch?
|
31
31
|
if @request.put? || @request.post?
|
32
|
-
|
32
|
+
calculated_hash != content_hash
|
33
33
|
else
|
34
34
|
false
|
35
35
|
end
|
@@ -47,8 +47,8 @@ module ApiAuth
|
|
47
47
|
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
51
|
-
find_header(%w[CONTENT-
|
50
|
+
def content_hash
|
51
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
52
52
|
end
|
53
53
|
|
54
54
|
def original_uri
|
@@ -15,11 +15,11 @@ module ApiAuth
|
|
15
15
|
@request
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def populate_content_hash
|
19
19
|
nil # doesn't appear to be possible
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
22
|
+
def content_hash_mismatch?
|
23
23
|
false
|
24
24
|
end
|
25
25
|
|
@@ -35,8 +35,8 @@ module ApiAuth
|
|
35
35
|
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
36
36
|
end
|
37
37
|
|
38
|
-
def
|
39
|
-
find_header(%w[CONTENT-
|
38
|
+
def content_hash
|
39
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
40
40
|
end
|
41
41
|
|
42
42
|
def original_uri
|
@@ -15,21 +15,21 @@ module ApiAuth
|
|
15
15
|
@request
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def calculated_hash
|
19
19
|
body = @request.body || ''
|
20
|
-
|
20
|
+
sha256_base64digest(body)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
return unless %w[POST PUT].include?(@request.
|
23
|
+
def populate_content_hash
|
24
|
+
return unless %w[POST PUT].include?(@request.http_method.to_s.upcase)
|
25
25
|
|
26
|
-
@request.headers['Content-
|
26
|
+
@request.headers['X-Authorization-Content-SHA256'] = calculated_hash
|
27
27
|
fetch_headers
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
if %w[POST PUT].include?(@request.
|
32
|
-
|
30
|
+
def content_hash_mismatch?
|
31
|
+
if %w[POST PUT].include?(@request.http_method.to_s.upcase)
|
32
|
+
calculated_hash != content_hash
|
33
33
|
else
|
34
34
|
false
|
35
35
|
end
|
@@ -40,15 +40,15 @@ module ApiAuth
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def http_method
|
43
|
-
@request.
|
43
|
+
@request.http_method.to_s.upcase
|
44
44
|
end
|
45
45
|
|
46
46
|
def content_type
|
47
47
|
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
51
|
-
find_header(%w[
|
50
|
+
def content_hash
|
51
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
52
52
|
end
|
53
53
|
|
54
54
|
def original_uri
|
@@ -15,22 +15,22 @@ module ApiAuth
|
|
15
15
|
@request
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def calculated_hash
|
19
19
|
body = @request.body.read
|
20
20
|
@request.body.rewind
|
21
|
-
|
21
|
+
sha256_base64digest(body)
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
24
|
+
def populate_content_hash
|
25
25
|
return if !@request.put? && !@request.post?
|
26
26
|
|
27
|
-
@request.env['
|
27
|
+
@request.env['HTTP_X_AUTHORIZATION_CONTENT_SHA256'] = calculated_hash
|
28
28
|
save_headers
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def content_hash_mismatch?
|
32
32
|
if @request.put? || @request.post?
|
33
|
-
|
33
|
+
calculated_hash != content_hash
|
34
34
|
else
|
35
35
|
false
|
36
36
|
end
|
@@ -48,8 +48,8 @@ module ApiAuth
|
|
48
48
|
find_header %w[HTTP_X_HMAC_CONTENT_TYPE HTTP_X_CONTENT_TYPE CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE]
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
52
|
-
find_header %w[
|
51
|
+
def content_hash
|
52
|
+
find_header %w[HTTP_X_AUTHORIZATION_CONTENT_SHA256]
|
53
53
|
end
|
54
54
|
|
55
55
|
def original_uri
|
@@ -12,19 +12,19 @@ module ApiAuth
|
|
12
12
|
@request
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
15
|
+
def calculated_hash
|
16
|
+
sha256_base64digest(body)
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
19
|
+
def populate_content_hash
|
20
20
|
return unless %w[POST PUT].include?(http_method)
|
21
21
|
|
22
|
-
@request['Content-
|
22
|
+
@request['X-Authorization-Content-SHA256'] = calculated_hash
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
25
|
+
def content_hash_mismatch?
|
26
26
|
if %w[POST PUT].include?(http_method)
|
27
|
-
|
27
|
+
calculated_hash != content_hash
|
28
28
|
else
|
29
29
|
false
|
30
30
|
end
|
@@ -38,8 +38,8 @@ module ApiAuth
|
|
38
38
|
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
42
|
-
find_header(%w[CONTENT-
|
41
|
+
def content_hash
|
42
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
43
43
|
end
|
44
44
|
|
45
45
|
def original_uri
|
@@ -15,20 +15,20 @@ module ApiAuth
|
|
15
15
|
@request
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
|
18
|
+
def calculated_hash
|
19
|
+
sha256_base64digest(@request.body || '')
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
22
|
+
def populate_content_hash
|
23
23
|
return unless @request.body
|
24
24
|
|
25
|
-
@request.headers['Content-
|
25
|
+
@request.headers['X-Authorization-Content-SHA256'] = calculated_hash
|
26
26
|
fetch_headers
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
29
|
+
def content_hash_mismatch?
|
30
30
|
if @request.body
|
31
|
-
|
31
|
+
calculated_hash != content_hash
|
32
32
|
else
|
33
33
|
false
|
34
34
|
end
|
@@ -46,8 +46,8 @@ module ApiAuth
|
|
46
46
|
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
47
47
|
end
|
48
48
|
|
49
|
-
def
|
50
|
-
find_header(%w[CONTENT-
|
49
|
+
def content_hash
|
50
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
51
51
|
end
|
52
52
|
|
53
53
|
def original_uri
|
@@ -15,7 +15,7 @@ module ApiAuth
|
|
15
15
|
@request
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def calculated_hash
|
19
19
|
if @request.respond_to?(:body_stream) && @request.body_stream
|
20
20
|
body = @request.body_stream.read
|
21
21
|
@request.body_stream.rewind
|
@@ -23,18 +23,18 @@ module ApiAuth
|
|
23
23
|
body = @request.body
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
sha256_base64digest(body || '')
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
29
|
+
def populate_content_hash
|
30
30
|
return unless @request.class::REQUEST_HAS_BODY
|
31
31
|
|
32
|
-
@request['Content-
|
32
|
+
@request['X-Authorization-Content-SHA256'] = calculated_hash
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
35
|
+
def content_hash_mismatch?
|
36
36
|
if @request.class::REQUEST_HAS_BODY
|
37
|
-
|
37
|
+
calculated_hash != content_hash
|
38
38
|
else
|
39
39
|
false
|
40
40
|
end
|
@@ -52,8 +52,8 @@ module ApiAuth
|
|
52
52
|
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
53
53
|
end
|
54
54
|
|
55
|
-
def
|
56
|
-
find_header(%w[
|
55
|
+
def content_hash
|
56
|
+
find_header(%w[X-Authorization-Content-SHA256])
|
57
57
|
end
|
58
58
|
|
59
59
|
def original_uri
|
@@ -15,26 +15,26 @@ module ApiAuth
|
|
15
15
|
@request
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def calculated_hash
|
19
19
|
if @request.body
|
20
20
|
body = @request.body.read
|
21
21
|
@request.body.rewind
|
22
22
|
else
|
23
23
|
body = ''
|
24
24
|
end
|
25
|
-
|
25
|
+
sha256_base64digest(body)
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
28
|
+
def populate_content_hash
|
29
29
|
return unless %w[POST PUT].include?(@request.request_method)
|
30
30
|
|
31
|
-
@request.env['Content-
|
31
|
+
@request.env['X-Authorization-Content-SHA256'] = calculated_hash
|
32
32
|
fetch_headers
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
35
|
+
def content_hash_mismatch?
|
36
36
|
if %w[POST PUT].include?(@request.request_method)
|
37
|
-
|
37
|
+
calculated_hash != content_hash
|
38
38
|
else
|
39
39
|
false
|
40
40
|
end
|
@@ -52,8 +52,8 @@ module ApiAuth
|
|
52
52
|
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
53
53
|
end
|
54
54
|
|
55
|
-
def
|
56
|
-
find_header(%w[
|
55
|
+
def content_hash
|
56
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
57
57
|
end
|
58
58
|
|
59
59
|
def original_uri
|
@@ -18,26 +18,26 @@ module ApiAuth
|
|
18
18
|
@request
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def calculated_hash
|
22
22
|
if @request.payload
|
23
23
|
body = @request.payload.read
|
24
24
|
@request.payload.instance_variable_get(:@stream).seek(0)
|
25
25
|
else
|
26
26
|
body = ''
|
27
27
|
end
|
28
|
-
|
28
|
+
sha256_base64digest(body)
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def populate_content_hash
|
32
32
|
return unless %w[post put].include?(@request.method.to_s)
|
33
33
|
|
34
|
-
@request.headers['Content-
|
34
|
+
@request.headers['X-Authorization-Content-SHA256'] = calculated_hash
|
35
35
|
save_headers
|
36
36
|
end
|
37
37
|
|
38
|
-
def
|
38
|
+
def content_hash_mismatch?
|
39
39
|
if %w[post put].include?(@request.method.to_s)
|
40
|
-
|
40
|
+
calculated_hash != content_hash
|
41
41
|
else
|
42
42
|
false
|
43
43
|
end
|
@@ -55,8 +55,8 @@ module ApiAuth
|
|
55
55
|
find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
|
56
56
|
end
|
57
57
|
|
58
|
-
def
|
59
|
-
find_header(%w[CONTENT-
|
58
|
+
def content_hash
|
59
|
+
find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
|
60
60
|
end
|
61
61
|
|
62
62
|
def original_uri
|
data/spec/api_auth_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'ApiAuth' do
|
4
4
|
describe 'generating secret keys' do
|
@@ -36,9 +36,9 @@ describe 'ApiAuth' do
|
|
36
36
|
ApiAuth.sign!(request, 'abc', '123')
|
37
37
|
end
|
38
38
|
|
39
|
-
it 'generates
|
39
|
+
it 'generates X-Authorization-Content-SHA256 header before signing' do
|
40
40
|
expect(ApiAuth::Headers).to receive(:new).and_return(headers)
|
41
|
-
expect(headers).to receive(:
|
41
|
+
expect(headers).to receive(:calculate_hash).ordered
|
42
42
|
expect(headers).to receive(:sign_header).ordered
|
43
43
|
|
44
44
|
ApiAuth.sign!(request, 'abc', '123')
|
@@ -58,7 +58,7 @@ describe 'ApiAuth' do
|
|
58
58
|
let(:request) do
|
59
59
|
Net::HTTP::Put.new('/resource.xml?foo=bar&bar=foo',
|
60
60
|
'content-type' => 'text/plain',
|
61
|
-
'content-
|
61
|
+
'content-hash' => '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
|
62
62
|
'date' => Time.now.utc.httpdate)
|
63
63
|
end
|
64
64
|
|
@@ -76,7 +76,7 @@ describe 'ApiAuth' do
|
|
76
76
|
let(:request) do
|
77
77
|
Net::HTTP::Put.new('/resource.xml?foo=bar&bar=foo',
|
78
78
|
'content-type' => 'text/plain',
|
79
|
-
'
|
79
|
+
'X-Authorization-Content-SHA256' => '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
|
80
80
|
'date' => Time.now.utc.httpdate)
|
81
81
|
end
|
82
82
|
|
@@ -94,8 +94,8 @@ describe 'ApiAuth' do
|
|
94
94
|
expect(ApiAuth.authentic?(signed_request, '456')).to eq false
|
95
95
|
end
|
96
96
|
|
97
|
-
it 'fails to validate non matching
|
98
|
-
request['
|
97
|
+
it 'fails to validate non matching hash' do
|
98
|
+
request['X-Authorization-Content-SHA256'] = '12345'
|
99
99
|
expect(ApiAuth.authentic?(signed_request, '123')).to eq false
|
100
100
|
end
|
101
101
|
|
@@ -125,7 +125,7 @@ describe 'ApiAuth' do
|
|
125
125
|
let(:request) do
|
126
126
|
new_request = Net::HTTP::Put.new('/resource.xml?foo=bar&bar=foo',
|
127
127
|
'content-type' => 'text/plain',
|
128
|
-
'
|
128
|
+
'X-Authorization-Content-SHA256' => '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
|
129
129
|
'date' => Time.now.utc.httpdate)
|
130
130
|
canonical_string = ApiAuth::Headers.new(new_request).canonical_string
|
131
131
|
signature = hmac('123', new_request, canonical_string, 'sha256')
|