api-auth 2.3.1 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +1 -1
- data/.travis.yml +10 -5
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -1
- data/README.md +64 -34
- data/VERSION +1 -1
- data/api_auth.gemspec +2 -2
- data/gemfiles/rails_5.gemfile +1 -3
- data/gemfiles/rails_51.gemfile +1 -1
- data/gemfiles/rails_52.gemfile +1 -1
- data/gemfiles/rails_60.gemfile +11 -0
- data/lib/api_auth/railtie.rb +6 -4
- data/spec/spec_helper.rb +1 -1
- metadata +8 -11
- data/gemfiles/rails_4.gemfile +0 -11
- data/gemfiles/rails_41.gemfile +0 -11
- data/gemfiles/rails_42.gemfile +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d436a907531dd36a529a79d60ef5192d6b65379e80a35545cd1640ec9c4a08cd
|
4
|
+
data.tar.gz: 2aaaffd472c764c872b740ba1a17870ad41dc9651863cc71c164a2e1ddfc2074
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 484fd40c118f14077f5e5a281729d776a06ff35b2c8c44864436a1ac4f4d2c540b842ff8dc469bf4519c31d8255af87777f552d7eb1e0b6233a3e2d91b4d6e38
|
7
|
+
data.tar.gz: e2b7f7861678234ead914d4fa06f15c25d4f43274c32e29f962c8e625f5a16c44e8e49840a6ab19b3832fe48af9e491c691b6c3ba4d23d5cadd3e3b7b4c66885
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -65,7 +65,7 @@ Naming/AccessorMethodName:
|
|
65
65
|
# Offense count: 3
|
66
66
|
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
67
67
|
# AllowedNames: io, id, to, by, on, in, at, ip, db
|
68
|
-
Naming/
|
68
|
+
Naming/MethodParameterName:
|
69
69
|
Exclude:
|
70
70
|
- 'lib/api_auth/base.rb'
|
71
71
|
- 'spec/railtie_spec.rb'
|
data/.travis.yml
CHANGED
@@ -5,13 +5,12 @@ rvm:
|
|
5
5
|
- 2.3.6
|
6
6
|
- 2.4.3
|
7
7
|
- 2.5.3
|
8
|
+
- 2.6.1
|
8
9
|
gemfile:
|
9
|
-
- gemfiles/rails_4.gemfile
|
10
|
-
- gemfiles/rails_41.gemfile
|
11
|
-
- gemfiles/rails_42.gemfile
|
12
10
|
- gemfiles/rails_5.gemfile
|
13
11
|
- gemfiles/rails_51.gemfile
|
14
12
|
- gemfiles/rails_52.gemfile
|
13
|
+
- gemfiles/rails_60.gemfile
|
15
14
|
- gemfiles/http2.gemfile
|
16
15
|
- gemfiles/http3.gemfile
|
17
16
|
- gemfiles/http4.gemfile
|
@@ -26,9 +25,15 @@ script:
|
|
26
25
|
|
27
26
|
matrix:
|
28
27
|
include:
|
29
|
-
- rvm: 2.
|
30
|
-
gemfile: gemfiles/
|
28
|
+
- rvm: 2.6.1
|
29
|
+
gemfile: gemfiles/rails_60.gemfile
|
31
30
|
env: TEST_SUITE="rubocop lib/ spec/"
|
31
|
+
exclude:
|
32
|
+
- rvm: 2.3.6
|
33
|
+
gemfile: gemfiles/rails_60.gemfile
|
34
|
+
- rvm: 2.4.3
|
35
|
+
gemfile: gemfiles/rails_60.gemfile
|
36
|
+
env: TEST_SUITE=rake
|
32
37
|
|
33
38
|
notifications:
|
34
39
|
email: false
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -21,19 +21,33 @@ have to be written in the same language as the clients.
|
|
21
21
|
## How it works
|
22
22
|
|
23
23
|
1. A canonical string is first created using your HTTP headers containing the
|
24
|
-
content-type, content-MD5, request
|
24
|
+
content-type, content-MD5, request path and the date/time stamp. If content-type or
|
25
25
|
content-MD5 are not present, then a blank string is used in their place. If the
|
26
26
|
timestamp isn't present, a valid HTTP date is automatically added to the
|
27
27
|
request. The canonical string is computed as follows:
|
28
28
|
|
29
|
-
|
29
|
+
```
|
30
|
+
canonical_string = "#{http method},#{content-type},#{content-MD5},#{request URI},#{timestamp}"
|
31
|
+
|
32
|
+
e.g.,
|
33
|
+
|
34
|
+
canonical_string = 'POST,application/json,,request_path,Tue, 30 May 2017 03:51:43 GMT'
|
35
|
+
```
|
30
36
|
|
31
37
|
2. This string is then used to create the signature which is a Base64 encoded
|
32
38
|
SHA1 HMAC, using the client's private secret key.
|
33
39
|
|
34
40
|
3. This signature is then added as the `Authorization` HTTP header in the form:
|
35
41
|
|
36
|
-
|
42
|
+
```
|
43
|
+
Authorization = APIAuth "#{client access id}:#{signature from step 2}"
|
44
|
+
```
|
45
|
+
|
46
|
+
A cURL request would look like:
|
47
|
+
|
48
|
+
```
|
49
|
+
curl -X POST --header 'Content-Type: application/json' --header "Date: Tue, 30 May 2017 03:51:43 GMT" --header "Authorization: ${AUTHORIZATION}" http://my-app.com/request_path`
|
50
|
+
```
|
37
51
|
|
38
52
|
5. On the server side, the SHA1 HMAC is computed in the same way using the
|
39
53
|
request headers and the client's secret key, which is known to only
|
@@ -63,7 +77,9 @@ For older version of Ruby or Rails, please use ApiAuth v2.1 and older.
|
|
63
77
|
The gem doesn't have any dependencies outside of having a working OpenSSL
|
64
78
|
configuration for your Ruby VM. To install:
|
65
79
|
|
66
|
-
|
80
|
+
```bash
|
81
|
+
[sudo] gem install api-auth
|
82
|
+
```
|
67
83
|
|
68
84
|
Please note the dash in the name versus the underscore.
|
69
85
|
|
@@ -89,25 +105,29 @@ Here's a sample implementation of signing a request created with RestClient.
|
|
89
105
|
Assuming you have a client access id and secret as follows:
|
90
106
|
|
91
107
|
``` ruby
|
92
|
-
|
93
|
-
|
108
|
+
@access_id = "1044"
|
109
|
+
@secret_key = ApiAuth.generate_secret_key
|
94
110
|
```
|
95
111
|
|
96
112
|
A typical RestClient PUT request may look like:
|
97
113
|
|
98
114
|
``` ruby
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
115
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
116
|
+
'Content-Type' => "text/plain",
|
117
|
+
'Date' => "Mon, 23 Jan 1984 03:29:56 GMT"
|
118
|
+
}
|
119
|
+
|
120
|
+
@request = RestClient::Request.new(
|
121
|
+
url: "/resource.xml?foo=bar&bar=foo",
|
122
|
+
headers: headers,
|
123
|
+
method: :put
|
124
|
+
)
|
105
125
|
```
|
106
126
|
|
107
127
|
To sign that request, simply call the `sign!` method as follows:
|
108
128
|
|
109
129
|
``` ruby
|
110
|
-
|
130
|
+
@signed_request = ApiAuth.sign!(@request, @access_id, @secret_key)
|
111
131
|
```
|
112
132
|
|
113
133
|
The proper `Authorization` request header has now been added to that request
|
@@ -121,23 +141,27 @@ method detection (like Curb or httpi), you can pass the http method as an option
|
|
121
141
|
into the sign! method like so:
|
122
142
|
|
123
143
|
``` ruby
|
124
|
-
|
144
|
+
@signed_request = ApiAuth.sign!(@request, @access_id, @secret_key, :override_http_method => "PUT")
|
125
145
|
```
|
126
146
|
|
127
147
|
If you want to use another digest existing in `OpenSSL::Digest`,
|
128
148
|
you can pass the http method as an option into the sign! method like so:
|
129
149
|
|
130
150
|
``` ruby
|
131
|
-
|
151
|
+
@signed_request = ApiAuth.sign!(@request, @access_id, @secret_key, :digest => 'sha256')
|
132
152
|
```
|
133
153
|
|
134
154
|
With the `digest` option, the `Authorization` header will be change from:
|
135
155
|
|
136
|
-
|
156
|
+
```
|
157
|
+
Authorization = APIAuth 'client access id':'signature'
|
158
|
+
```
|
137
159
|
|
138
160
|
to:
|
139
161
|
|
140
|
-
|
162
|
+
```
|
163
|
+
Authorization = APIAuth-HMAC-DIGEST_NAME 'client access id':'signature'
|
164
|
+
```
|
141
165
|
|
142
166
|
### ActiveResource Clients
|
143
167
|
|
@@ -145,9 +169,9 @@ ApiAuth can transparently protect your ActiveResource communications with a
|
|
145
169
|
single configuration line:
|
146
170
|
|
147
171
|
``` ruby
|
148
|
-
|
149
|
-
|
150
|
-
|
172
|
+
class MyResource < ActiveResource::Base
|
173
|
+
with_api_auth(access_id, secret_key)
|
174
|
+
end
|
151
175
|
```
|
152
176
|
|
153
177
|
This will automatically sign all outgoing ActiveResource requests from your app.
|
@@ -169,26 +193,28 @@ clients as well as verifying incoming API requests.
|
|
169
193
|
To generate a Base64 encoded API key for a client:
|
170
194
|
|
171
195
|
``` ruby
|
172
|
-
|
196
|
+
ApiAuth.generate_secret_key
|
173
197
|
```
|
174
198
|
|
175
199
|
To validate whether or not a request is authentic:
|
176
200
|
|
177
201
|
``` ruby
|
178
|
-
|
202
|
+
ApiAuth.authentic?(signed_request, secret_key)
|
179
203
|
```
|
180
204
|
|
181
205
|
The `authentic?` method uses the digest specified in the `Authorization` header.
|
182
206
|
For example SHA256 for:
|
183
207
|
|
184
|
-
|
208
|
+
```
|
209
|
+
Authorization = APIAuth-HMAC-SHA256 'client access id':'signature'
|
210
|
+
```
|
185
211
|
|
186
212
|
And by default SHA1 if the HMAC-DIGEST is not specified.
|
187
213
|
|
188
214
|
If you want to force the usage of another digest method, you should pass it as an option parameter:
|
189
215
|
|
190
216
|
``` ruby
|
191
|
-
|
217
|
+
ApiAuth.authentic?(signed_request, secret_key, :digest => 'sha256')
|
192
218
|
```
|
193
219
|
|
194
220
|
For security, requests dated older or newer than a certain timespan are considered inauthentic.
|
@@ -199,13 +225,13 @@ can't be dated into the far future.
|
|
199
225
|
The default span is 15 minutes, but you can override this:
|
200
226
|
|
201
227
|
```ruby
|
202
|
-
|
228
|
+
ApiAuth.authentic?(signed_request, secret_key, :clock_skew => 60) # or 1.minute in ActiveSupport
|
203
229
|
```
|
204
230
|
|
205
231
|
If you want to sign custom headers, you can pass them as an array of strings in the options like so:
|
206
232
|
|
207
233
|
``` ruby
|
208
|
-
|
234
|
+
ApiAuth.authentic?(signed_request, secret_key, headers_to_sign: %w[HTTP_HEADER_NAME])
|
209
235
|
```
|
210
236
|
|
211
237
|
With the specified headers values being at the end of the canonical string in the same order.
|
@@ -216,7 +242,7 @@ In order to obtain the secret key for the client, you first need to look up the
|
|
216
242
|
client's access_id. ApiAuth can pull that from the request headers for you:
|
217
243
|
|
218
244
|
``` ruby
|
219
|
-
|
245
|
+
ApiAuth.access_id(signed_request)
|
220
246
|
```
|
221
247
|
|
222
248
|
Once you've looked up the client's record via the access id, you can then verify
|
@@ -228,12 +254,12 @@ Here's a sample method that can be used in a `before_action` if your server is a
|
|
228
254
|
Rails app:
|
229
255
|
|
230
256
|
``` ruby
|
231
|
-
|
257
|
+
before_action :api_authenticate
|
232
258
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
259
|
+
def api_authenticate
|
260
|
+
@current_account = Account.find_by_access_id(ApiAuth.access_id(request))
|
261
|
+
head(:unauthorized) unless @current_account && ApiAuth.authentic?(request, @current_account.secret_key)
|
262
|
+
end
|
237
263
|
```
|
238
264
|
|
239
265
|
## Development
|
@@ -246,11 +272,15 @@ To run the tests:
|
|
246
272
|
|
247
273
|
Install the dependencies for a particular Rails version by specifying a gemfile in `gemfiles` directory:
|
248
274
|
|
249
|
-
|
275
|
+
```
|
276
|
+
BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle install
|
277
|
+
```
|
250
278
|
|
251
279
|
Run the tests with those dependencies:
|
252
280
|
|
253
|
-
|
281
|
+
```
|
282
|
+
BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle exec rake
|
283
|
+
```
|
254
284
|
|
255
285
|
If you'd like to add support for additional HTTP clients, check out the already
|
256
286
|
implemented drivers in `lib/api_auth/request_drivers` for reference. All of
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.4.0
|
data/api_auth.gemspec
CHANGED
@@ -11,9 +11,9 @@ Gem::Specification.new do |s|
|
|
11
11
|
|
12
12
|
s.required_ruby_version = '>= 2.3.0'
|
13
13
|
|
14
|
-
s.add_development_dependency 'actionpack', '< 6.
|
14
|
+
s.add_development_dependency 'actionpack', '< 6.1', '> 4.0'
|
15
15
|
s.add_development_dependency 'activeresource', '>= 4.0'
|
16
|
-
s.add_development_dependency 'activesupport', '< 6.
|
16
|
+
s.add_development_dependency 'activesupport', '< 6.1', '> 4.0'
|
17
17
|
s.add_development_dependency 'amatch'
|
18
18
|
s.add_development_dependency 'appraisal'
|
19
19
|
s.add_development_dependency 'curb', '~> 0.8'
|
data/gemfiles/rails_5.gemfile
CHANGED
@@ -3,9 +3,7 @@
|
|
3
3
|
source 'https://rubygems.org'
|
4
4
|
|
5
5
|
gem 'actionpack', '~> 5.0.2'
|
6
|
-
gem 'activeresource', '~> 5.0.0'
|
6
|
+
gem 'activeresource', '~> 5.0.0'
|
7
7
|
gem 'activesupport', '~> 5.0.2'
|
8
8
|
|
9
|
-
gem 'rubocop'
|
10
|
-
|
11
9
|
gemspec path: '../'
|
data/gemfiles/rails_51.gemfile
CHANGED
data/gemfiles/rails_52.gemfile
CHANGED
data/lib/api_auth/railtie.rb
CHANGED
@@ -13,7 +13,9 @@ module ApiAuth
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
ActiveSupport.on_load(:action_controller) do
|
17
|
+
ActionController::Base.include(ControllerMethods::InstanceMethods)
|
18
|
+
end
|
17
19
|
end # ControllerMethods
|
18
20
|
|
19
21
|
module ActiveResourceExtension # :nodoc:
|
@@ -78,9 +80,9 @@ module ApiAuth
|
|
78
80
|
end
|
79
81
|
end # Connection
|
80
82
|
|
81
|
-
|
82
|
-
ActiveResource::Base.
|
83
|
-
ActiveResource::Connection.
|
83
|
+
ActiveSupport.on_load(:active_resource) do
|
84
|
+
ActiveResource::Base.include(ActiveResourceApiAuth)
|
85
|
+
ActiveResource::Connection.include(Connection)
|
84
86
|
end
|
85
87
|
end # ActiveResourceExtension
|
86
88
|
end # Rails
|
data/spec/spec_helper.rb
CHANGED
@@ -21,4 +21,4 @@ require 'net/http/post/multipart'
|
|
21
21
|
|
22
22
|
# Requires supporting files with custom matchers and macros, etc,
|
23
23
|
# in ./support/ and its subdirectories.
|
24
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
24
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |f| require f }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api-auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mauricio Gomes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -16,7 +16,7 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "<"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '6.
|
19
|
+
version: '6.1'
|
20
20
|
- - ">"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '4.0'
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - "<"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '6.
|
29
|
+
version: '6.1'
|
30
30
|
- - ">"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '4.0'
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - "<"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '6.
|
53
|
+
version: '6.1'
|
54
54
|
- - ">"
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
version: '4.0'
|
@@ -60,7 +60,7 @@ dependencies:
|
|
60
60
|
requirements:
|
61
61
|
- - "<"
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: '6.
|
63
|
+
version: '6.1'
|
64
64
|
- - ">"
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: '4.0'
|
@@ -255,12 +255,10 @@ files:
|
|
255
255
|
- gemfiles/http2.gemfile
|
256
256
|
- gemfiles/http3.gemfile
|
257
257
|
- gemfiles/http4.gemfile
|
258
|
-
- gemfiles/rails_4.gemfile
|
259
|
-
- gemfiles/rails_41.gemfile
|
260
|
-
- gemfiles/rails_42.gemfile
|
261
258
|
- gemfiles/rails_5.gemfile
|
262
259
|
- gemfiles/rails_51.gemfile
|
263
260
|
- gemfiles/rails_52.gemfile
|
261
|
+
- gemfiles/rails_60.gemfile
|
264
262
|
- lib/api-auth.rb
|
265
263
|
- lib/api_auth.rb
|
266
264
|
- lib/api_auth/base.rb
|
@@ -313,8 +311,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
313
311
|
- !ruby/object:Gem::Version
|
314
312
|
version: '0'
|
315
313
|
requirements: []
|
316
|
-
|
317
|
-
rubygems_version: 2.7.7
|
314
|
+
rubygems_version: 3.1.2
|
318
315
|
signing_key:
|
319
316
|
specification_version: 4
|
320
317
|
summary: Simple HMAC authentication for your APIs
|
data/gemfiles/rails_4.gemfile
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# This file was generated by Appraisal
|
2
|
-
|
3
|
-
source 'https://rubygems.org'
|
4
|
-
|
5
|
-
gem 'actionpack', '~> 4.0.4'
|
6
|
-
gem 'activeresource', '~> 4.0.0'
|
7
|
-
gem 'activesupport', '~> 4.0.4'
|
8
|
-
gem 'rake', '< 11.0', platforms: :ruby_18
|
9
|
-
gem 'tins', '< 1.7', platforms: :ruby_19
|
10
|
-
|
11
|
-
gemspec path: '../'
|
data/gemfiles/rails_41.gemfile
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# This file was generated by Appraisal
|
2
|
-
|
3
|
-
source 'https://rubygems.org'
|
4
|
-
|
5
|
-
gem 'actionpack', '~> 4.1.0'
|
6
|
-
gem 'activeresource', '~> 4.0.0'
|
7
|
-
gem 'activesupport', '~> 4.1.0'
|
8
|
-
gem 'rake', '< 11.0', platforms: :ruby_18
|
9
|
-
gem 'tins', '< 1.7', platforms: :ruby_19
|
10
|
-
|
11
|
-
gemspec path: '../'
|
data/gemfiles/rails_42.gemfile
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# This file was generated by Appraisal
|
2
|
-
|
3
|
-
source 'https://rubygems.org'
|
4
|
-
|
5
|
-
gem 'actionpack', '~> 4.2.0'
|
6
|
-
gem 'activeresource', '~> 4.0.0'
|
7
|
-
gem 'activesupport', '~> 4.2.0'
|
8
|
-
gem 'rake', '< 11.0', platforms: :ruby_18
|
9
|
-
gem 'tins', '< 1.7', platforms: :ruby_19
|
10
|
-
|
11
|
-
gemspec path: '../'
|