api-auth 2.3.1 → 2.4.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 +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: '../'
|