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
|
@@ -3,16 +3,16 @@ require 'spec_helper'
|
|
|
3
3
|
if defined?(ActionController::Request)
|
|
4
4
|
|
|
5
5
|
describe ApiAuth::RequestDrivers::ActionControllerRequest do
|
|
6
|
-
|
|
7
|
-
let(:
|
|
6
|
+
let(:timestamp) { Time.now.utc.httpdate }
|
|
7
|
+
let(:content_sha256) { '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=' }
|
|
8
8
|
|
|
9
9
|
let(:request) do
|
|
10
10
|
ActionController::Request.new(
|
|
11
|
-
'AUTHORIZATION'
|
|
11
|
+
'AUTHORIZATION' => 'APIAuth 1044:12345',
|
|
12
12
|
'PATH_INFO' => '/resource.xml',
|
|
13
13
|
'QUERY_STRING' => 'foo=bar&bar=foo',
|
|
14
14
|
'REQUEST_METHOD' => 'PUT',
|
|
15
|
-
'
|
|
15
|
+
'HTTP_X_AUTHORIZATION_CONTENT_SHA256' => content_sha256,
|
|
16
16
|
'CONTENT_TYPE' => 'text/plain',
|
|
17
17
|
'CONTENT_LENGTH' => '11',
|
|
18
18
|
'HTTP_DATE' => timestamp,
|
|
@@ -20,217 +20,260 @@ if defined?(ActionController::Request)
|
|
|
20
20
|
)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
let(:request2) do
|
|
24
|
+
ActionController::Request.new(
|
|
25
|
+
'AUTHORIZATION' => 'APIAuth 1044:12345',
|
|
26
|
+
'PATH_INFO' => '/resource.xml',
|
|
27
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
|
28
|
+
'REQUEST_METHOD' => 'PUT',
|
|
29
|
+
'X_AUTHORIZATION_CONTENT_SHA256' => content_sha256,
|
|
30
|
+
'CONTENT_TYPE' => 'text/plain',
|
|
31
|
+
'CONTENT_LENGTH' => '11',
|
|
32
|
+
'HTTP_DATE' => timestamp,
|
|
33
|
+
'rack.input' => StringIO.new("hello\nworld")
|
|
34
|
+
)
|
|
35
|
+
end
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
let(:request3) do
|
|
38
|
+
ActionController::Request.new(
|
|
39
|
+
'AUTHORIZATION' => 'APIAuth 1044:12345',
|
|
40
|
+
'PATH_INFO' => '/resource.xml',
|
|
41
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
|
42
|
+
'REQUEST_METHOD' => 'PUT',
|
|
43
|
+
'X-AUTHORIZATION-CONTENT-SHA256' => content_sha256,
|
|
44
|
+
'CONTENT_TYPE' => 'text/plain',
|
|
45
|
+
'CONTENT_LENGTH' => '11',
|
|
46
|
+
'HTTP_DATE' => timestamp,
|
|
47
|
+
'rack.input' => StringIO.new("hello\nworld")
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
subject(:driven_request) { ApiAuth::RequestDrivers::ActionControllerRequest.new(request) }
|
|
52
|
+
|
|
53
|
+
describe 'getting headers correctly' do
|
|
54
|
+
it 'gets the content_type' do
|
|
27
55
|
expect(driven_request.content_type).to eq('text/plain')
|
|
28
56
|
end
|
|
29
57
|
|
|
30
|
-
it
|
|
31
|
-
expect(driven_request.
|
|
58
|
+
it 'gets the content_hash' do
|
|
59
|
+
expect(driven_request.content_hash).to eq(content_sha256)
|
|
32
60
|
end
|
|
33
61
|
|
|
34
|
-
it
|
|
62
|
+
it 'gets the content_hash for request 2' do
|
|
63
|
+
example_request = ApiAuth::RequestDrivers::ActionControllerRequest.new(request2)
|
|
64
|
+
expect(example_request.content_hash).to eq(content_sha256)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'gets the content_hash for request 3' do
|
|
68
|
+
example_request = ApiAuth::RequestDrivers::ActionControllerRequest.new(request3)
|
|
69
|
+
expect(example_request.content_hash).to eq(content_sha256)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'gets the request_uri' do
|
|
35
73
|
expect(driven_request.request_uri).to eq('/resource.xml?foo=bar&bar=foo')
|
|
36
74
|
end
|
|
37
75
|
|
|
38
|
-
it
|
|
76
|
+
it 'gets the timestamp' do
|
|
39
77
|
expect(driven_request.timestamp).to eq(timestamp)
|
|
40
78
|
end
|
|
41
79
|
|
|
42
|
-
it
|
|
80
|
+
it 'gets the authorization_header' do
|
|
43
81
|
expect(driven_request.authorization_header).to eq('APIAuth 1044:12345')
|
|
44
82
|
end
|
|
45
83
|
|
|
46
|
-
describe
|
|
47
|
-
it
|
|
48
|
-
expect(driven_request.
|
|
84
|
+
describe '#calculated_hash' do
|
|
85
|
+
it 'calculates hash from the body' do
|
|
86
|
+
expect(driven_request.calculated_hash).to eq('JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g=')
|
|
49
87
|
end
|
|
50
88
|
|
|
51
|
-
it
|
|
89
|
+
it 'treats no body as empty string' do
|
|
52
90
|
request.env['rack.input'] = StringIO.new
|
|
53
91
|
request.env['CONTENT_LENGTH'] = 0
|
|
54
|
-
expect(driven_request.
|
|
92
|
+
expect(driven_request.calculated_hash).to eq(content_sha256)
|
|
55
93
|
end
|
|
56
94
|
end
|
|
57
95
|
|
|
58
|
-
describe
|
|
59
|
-
context
|
|
96
|
+
describe 'http_method' do
|
|
97
|
+
context 'when put request' do
|
|
60
98
|
let(:request) do
|
|
61
99
|
ActionController::Request.new('REQUEST_METHOD' => 'PUT')
|
|
62
100
|
end
|
|
63
101
|
|
|
64
|
-
it
|
|
102
|
+
it 'returns upcased put' do
|
|
65
103
|
expect(driven_request.http_method).to eq('PUT')
|
|
66
104
|
end
|
|
67
105
|
end
|
|
68
106
|
|
|
69
|
-
context
|
|
107
|
+
context 'when get request' do
|
|
70
108
|
let(:request) do
|
|
71
109
|
ActionController::Request.new('REQUEST_METHOD' => 'GET')
|
|
72
110
|
end
|
|
73
111
|
|
|
74
|
-
it
|
|
112
|
+
it 'returns upcased get' do
|
|
75
113
|
expect(driven_request.http_method).to eq('GET')
|
|
76
114
|
end
|
|
77
115
|
end
|
|
78
116
|
end
|
|
79
117
|
end
|
|
80
118
|
|
|
81
|
-
describe
|
|
119
|
+
describe 'setting headers correctly' do
|
|
82
120
|
let(:request) do
|
|
83
121
|
ActionController::Request.new(
|
|
84
|
-
'PATH_INFO'
|
|
85
|
-
'QUERY_STRING'
|
|
122
|
+
'PATH_INFO' => '/resource.xml',
|
|
123
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
|
86
124
|
'REQUEST_METHOD' => 'PUT',
|
|
87
|
-
'CONTENT_TYPE'
|
|
125
|
+
'CONTENT_TYPE' => 'text/plain',
|
|
88
126
|
'CONTENT_LENGTH' => '11',
|
|
89
|
-
'rack.input'
|
|
127
|
+
'rack.input' => StringIO.new("hello\nworld")
|
|
90
128
|
)
|
|
91
129
|
end
|
|
92
130
|
|
|
93
|
-
describe
|
|
94
|
-
context
|
|
95
|
-
it "doesn't populate content
|
|
131
|
+
describe '#populate_content_hash' do
|
|
132
|
+
context 'when getting' do
|
|
133
|
+
it "doesn't populate content hash" do
|
|
96
134
|
request.env['REQUEST_METHOD'] = 'GET'
|
|
97
|
-
driven_request.
|
|
98
|
-
expect(request.env[
|
|
135
|
+
driven_request.populate_content_hash
|
|
136
|
+
expect(request.env['X-Authorization-Content-SHA256']).to be_nil
|
|
99
137
|
end
|
|
100
138
|
end
|
|
101
139
|
|
|
102
|
-
context
|
|
103
|
-
it
|
|
140
|
+
context 'when posting' do
|
|
141
|
+
it 'populates content hash' do
|
|
104
142
|
request.env['REQUEST_METHOD'] = 'POST'
|
|
105
|
-
driven_request.
|
|
106
|
-
expect(request.env[
|
|
143
|
+
driven_request.populate_content_hash
|
|
144
|
+
expect(request.env['X-Authorization-Content-SHA256']).to eq('JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g=')
|
|
107
145
|
end
|
|
108
146
|
|
|
109
|
-
it
|
|
110
|
-
driven_request.
|
|
111
|
-
expect(driven_request.
|
|
147
|
+
it 'refreshes the cached headers' do
|
|
148
|
+
driven_request.populate_content_hash
|
|
149
|
+
expect(driven_request.content_hash).to eq('JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g=')
|
|
112
150
|
end
|
|
113
151
|
end
|
|
114
152
|
|
|
115
|
-
context
|
|
116
|
-
it
|
|
153
|
+
context 'when putting' do
|
|
154
|
+
it 'populates content hash' do
|
|
117
155
|
request.env['REQUEST_METHOD'] = 'PUT'
|
|
118
|
-
driven_request.
|
|
119
|
-
expect(request.env[
|
|
156
|
+
driven_request.populate_content_hash
|
|
157
|
+
expect(request.env['X-Authorization-Content-SHA256']).to eq('JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g=')
|
|
120
158
|
end
|
|
121
159
|
|
|
122
|
-
it
|
|
123
|
-
driven_request.
|
|
124
|
-
expect(driven_request.
|
|
160
|
+
it 'refreshes the cached headers' do
|
|
161
|
+
driven_request.populate_content_hash
|
|
162
|
+
expect(driven_request.content_hash).to eq('JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g=')
|
|
125
163
|
end
|
|
126
164
|
end
|
|
127
165
|
|
|
128
|
-
context
|
|
129
|
-
it "doesn't populate content
|
|
166
|
+
context 'when deleting' do
|
|
167
|
+
it "doesn't populate content hash" do
|
|
130
168
|
request.env['REQUEST_METHOD'] = 'DELETE'
|
|
131
|
-
driven_request.
|
|
132
|
-
expect(request.env[
|
|
169
|
+
driven_request.populate_content_hash
|
|
170
|
+
expect(request.env['X-Authorization-Content-SHA256']).to be_nil
|
|
133
171
|
end
|
|
134
172
|
end
|
|
135
|
-
|
|
136
173
|
end
|
|
137
174
|
|
|
138
|
-
describe
|
|
175
|
+
describe '#set_date' do
|
|
139
176
|
before do
|
|
140
177
|
allow(Time).to receive_message_chain(:now, :utc, :httpdate).and_return(timestamp)
|
|
141
178
|
end
|
|
142
179
|
|
|
143
|
-
it
|
|
180
|
+
it 'sets the date header of the request' do
|
|
144
181
|
driven_request.set_date
|
|
145
182
|
expect(request.env['HTTP_DATE']).to eq(timestamp)
|
|
146
183
|
end
|
|
147
184
|
|
|
148
|
-
it
|
|
185
|
+
it 'refreshes the cached headers' do
|
|
149
186
|
driven_request.set_date
|
|
150
187
|
expect(driven_request.timestamp).to eq(timestamp)
|
|
151
188
|
end
|
|
152
189
|
end
|
|
153
190
|
|
|
154
|
-
describe
|
|
155
|
-
it
|
|
191
|
+
describe '#set_auth_header' do
|
|
192
|
+
it 'sets the auth header' do
|
|
156
193
|
driven_request.set_auth_header('APIAuth 1044:54321')
|
|
157
194
|
expect(request.env['Authorization']).to eq('APIAuth 1044:54321')
|
|
158
195
|
end
|
|
159
196
|
end
|
|
160
197
|
end
|
|
161
198
|
|
|
162
|
-
describe
|
|
163
|
-
context
|
|
199
|
+
describe 'content_hash_mismatch?' do
|
|
200
|
+
context 'when getting' do
|
|
164
201
|
before do
|
|
165
202
|
request.env['REQUEST_METHOD'] = 'GET'
|
|
166
203
|
end
|
|
167
204
|
|
|
168
|
-
it
|
|
169
|
-
expect(driven_request.
|
|
205
|
+
it 'is false' do
|
|
206
|
+
expect(driven_request.content_hash_mismatch?).to be false
|
|
170
207
|
end
|
|
171
208
|
end
|
|
172
209
|
|
|
173
|
-
context
|
|
210
|
+
context 'when posting' do
|
|
174
211
|
before do
|
|
175
212
|
request.env['REQUEST_METHOD'] = 'POST'
|
|
176
213
|
end
|
|
177
214
|
|
|
178
|
-
context
|
|
215
|
+
context 'when calculated matches sent' do
|
|
179
216
|
before do
|
|
180
|
-
request.env[
|
|
217
|
+
request.env['X-Authorization-Content-SHA256'] = 'JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g='
|
|
181
218
|
end
|
|
182
219
|
|
|
183
|
-
it
|
|
184
|
-
expect(driven_request.
|
|
220
|
+
it 'is false' do
|
|
221
|
+
expect(driven_request.content_hash_mismatch?).to be false
|
|
185
222
|
end
|
|
186
223
|
end
|
|
187
224
|
|
|
188
225
|
context "when calculated doesn't match sent" do
|
|
189
226
|
before do
|
|
190
|
-
request.env[
|
|
227
|
+
request.env['X-Authorization-Content-SHA256'] = '3'
|
|
191
228
|
end
|
|
192
229
|
|
|
193
|
-
it
|
|
194
|
-
expect(driven_request.
|
|
230
|
+
it 'is true' do
|
|
231
|
+
expect(driven_request.content_hash_mismatch?).to be true
|
|
195
232
|
end
|
|
196
233
|
end
|
|
197
234
|
end
|
|
198
235
|
|
|
199
|
-
context
|
|
236
|
+
context 'when putting' do
|
|
200
237
|
before do
|
|
201
238
|
request.env['REQUEST_METHOD'] = 'PUT'
|
|
202
239
|
end
|
|
203
240
|
|
|
204
|
-
context
|
|
241
|
+
context 'when calculated matches sent' do
|
|
205
242
|
before do
|
|
206
|
-
request.env[
|
|
243
|
+
request.env['X-Authorization-Content-SHA256'] = 'JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g='
|
|
207
244
|
end
|
|
208
245
|
|
|
209
|
-
it
|
|
210
|
-
expect(driven_request.
|
|
246
|
+
it 'is false' do
|
|
247
|
+
expect(driven_request.content_hash_mismatch?).to be false
|
|
211
248
|
end
|
|
212
249
|
end
|
|
213
250
|
|
|
214
251
|
context "when calculated doesn't match sent" do
|
|
215
252
|
before do
|
|
216
|
-
request.env[
|
|
253
|
+
request.env['X-Authorization-Content-SHA256'] = '3'
|
|
217
254
|
end
|
|
218
255
|
|
|
219
|
-
it
|
|
220
|
-
expect(driven_request.
|
|
256
|
+
it 'is true' do
|
|
257
|
+
expect(driven_request.content_hash_mismatch?).to be true
|
|
221
258
|
end
|
|
222
259
|
end
|
|
223
260
|
end
|
|
224
261
|
|
|
225
|
-
context
|
|
262
|
+
context 'when deleting' do
|
|
226
263
|
before do
|
|
227
264
|
request.env['REQUEST_METHOD'] = 'DELETE'
|
|
228
265
|
end
|
|
229
266
|
|
|
230
|
-
it
|
|
231
|
-
expect(driven_request.
|
|
267
|
+
it 'is false' do
|
|
268
|
+
expect(driven_request.content_hash_mismatch?).to be false
|
|
232
269
|
end
|
|
233
270
|
end
|
|
234
271
|
end
|
|
235
272
|
end
|
|
273
|
+
|
|
274
|
+
describe 'fetch_headers' do
|
|
275
|
+
it 'returns request headers' do
|
|
276
|
+
expect(driven_request.fetch_headers).to include('CONTENT-TYPE' => 'text/plain')
|
|
277
|
+
end
|
|
278
|
+
end
|
|
236
279
|
end
|