api-auth 2.3.1 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +67 -0
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +16 -3
  5. data/.rubocop_todo.yml +30 -20
  6. data/Appraisals +12 -18
  7. data/CHANGELOG.md +16 -0
  8. data/Gemfile +0 -2
  9. data/README.md +82 -50
  10. data/VERSION +1 -1
  11. data/api_auth.gemspec +11 -4
  12. data/gemfiles/rails_52.gemfile +5 -5
  13. data/gemfiles/rails_60.gemfile +9 -0
  14. data/gemfiles/rails_61.gemfile +9 -0
  15. data/lib/api_auth/base.rb +2 -2
  16. data/lib/api_auth/headers.rb +6 -6
  17. data/lib/api_auth/helpers.rb +2 -2
  18. data/lib/api_auth/railtie.rb +13 -5
  19. data/lib/api_auth/request_drivers/action_controller.rb +8 -8
  20. data/lib/api_auth/request_drivers/curb.rb +4 -4
  21. data/lib/api_auth/request_drivers/faraday.rb +11 -11
  22. data/lib/api_auth/request_drivers/grape_request.rb +8 -8
  23. data/lib/api_auth/request_drivers/http.rb +8 -8
  24. data/lib/api_auth/request_drivers/httpi.rb +8 -8
  25. data/lib/api_auth/request_drivers/net_http.rb +8 -8
  26. data/lib/api_auth/request_drivers/rack.rb +8 -8
  27. data/lib/api_auth/request_drivers/rest_client.rb +8 -8
  28. data/spec/api_auth_spec.rb +8 -8
  29. data/spec/headers_spec.rb +26 -26
  30. data/spec/helpers_spec.rb +1 -1
  31. data/spec/railtie_spec.rb +3 -3
  32. data/spec/request_drivers/action_controller_spec.rb +74 -35
  33. data/spec/request_drivers/action_dispatch_spec.rb +74 -35
  34. data/spec/request_drivers/curb_spec.rb +8 -8
  35. data/spec/request_drivers/faraday_spec.rb +43 -43
  36. data/spec/request_drivers/grape_request_spec.rb +33 -32
  37. data/spec/request_drivers/http_spec.rb +23 -23
  38. data/spec/request_drivers/httpi_spec.rb +22 -22
  39. data/spec/request_drivers/net_http_spec.rb +23 -23
  40. data/spec/request_drivers/rack_spec.rb +35 -35
  41. data/spec/request_drivers/rest_client_spec.rb +36 -36
  42. data/spec/spec_helper.rb +1 -1
  43. metadata +52 -30
  44. data/.travis.yml +0 -34
  45. data/gemfiles/http2.gemfile +0 -7
  46. data/gemfiles/http3.gemfile +0 -7
  47. data/gemfiles/http4.gemfile +0 -7
  48. data/gemfiles/rails_4.gemfile +0 -11
  49. data/gemfiles/rails_41.gemfile +0 -11
  50. data/gemfiles/rails_42.gemfile +0 -11
  51. data/gemfiles/rails_5.gemfile +0 -11
  52. data/gemfiles/rails_51.gemfile +0 -9
  53. data/spec/.rubocop.yml +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5a7d758deeb4447ee54a3024647e2fb02a4cca21bd4966bd902f381bcadf80a
4
- data.tar.gz: ebfad82648a644a014d4d1b316c664564ba3add87db5033395ffd100bef9b988
3
+ metadata.gz: 232d1199b2fd74328e77ba9dd3362789798585b3d88df7c6d4688cf843475190
4
+ data.tar.gz: 879689b7f0b691212e0c14a80e087a041769241221b7a88f094c1003b29cfa9c
5
5
  SHA512:
6
- metadata.gz: c0f369dd45bad4407dacbfdae026d98fea20368f6d3deff3cbf1bdb7fd57abdb6495bbaa8098fc051204d0cfd9ab9733b8a42fca53114e60a05da863f83f2b9a
7
- data.tar.gz: ef53f902cc3786257cadadaecf6009732de47a643cabf728f928ff8cb63933c04b59537a850f96d4729c8cb0c04e588c0b8521f630c3a318b3ebec4c5c8d7ef4
6
+ metadata.gz: 2cb0fbdf6f5984f7334bdfa8a16309837c35b146eab39cd723203cd6861c9ce1e51d66fa2f73a3bb6a9490eaec2af0e3c73b34a03726d26360fc664aa7095f32
7
+ data.tar.gz: 9a1e90785610686db8c1a84943d138f9528dd5ce28965774cfe3112ea74850d898694a7a2bd458ef513f0fd48db56015b8662c53ec78ec38d714080b6f59ed68
@@ -0,0 +1,67 @@
1
+ name: main
2
+ on:
3
+ - push
4
+ - pull_request
5
+ jobs:
6
+ rspec:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ fail-fast: true
10
+ matrix:
11
+ ruby-version:
12
+ - 2.5
13
+ - 2.6
14
+ - 2.7
15
+ - 3.0
16
+ gemfile:
17
+ - rails_52.gemfile
18
+ - rails_60.gemfile
19
+ - rails_61.gemfile
20
+ exclude:
21
+ - ruby-version: [ 2.6, 2.7, 3.0 ]
22
+ gemfile: rails_52.gemfile
23
+ - ruby-version: 3.0
24
+ gemfile: rails_60.gemfile
25
+ steps:
26
+ - name: Install packages required for `curb` gem
27
+ run: |
28
+ sudo apt-get update
29
+ sudo apt-get install -y libcurl4 libcurl3-gnutls libcurl4-openssl-dev
30
+
31
+ - name: Checkout repository
32
+ uses: actions/checkout@v2
33
+
34
+ - name: Install Ruby
35
+ uses: ruby/setup-ruby@v1
36
+ with:
37
+ ruby-version: ${{ matrix.ruby-version }}
38
+ bundler-cache: true
39
+
40
+ - name: Install required gems
41
+ run: BUNDLE_GEMFILE=gemfiles/${{ matrix.gemfile }} bundle install
42
+
43
+ - name: Run rspec tests
44
+ run: BUNDLE_GEMFILE=gemfiles/${{ matrix.gemfile }} bundle exec rspec
45
+
46
+ rubocop:
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - name: Install packages required for `curb` gem
50
+ run: |
51
+ sudo apt-get update
52
+ sudo apt-get install -y libcurl4 libcurl3-gnutls libcurl4-openssl-dev
53
+
54
+ - name: Checkout repository
55
+ uses: actions/checkout@v2
56
+
57
+ - name: Install Ruby
58
+ uses: ruby/setup-ruby@v1
59
+ with:
60
+ ruby-version: 3.0
61
+ bundler-cache: true
62
+
63
+ - name: Install required gems
64
+ run: bundle install
65
+
66
+ - name: Run rubocop
67
+ run: bundle exec rubocop
data/.gitignore CHANGED
@@ -8,4 +8,6 @@
8
8
  /doc
9
9
  /.yardoc
10
10
  gemfiles/*.lock
11
+ gemfiles/.bundle/
11
12
  /.idea
13
+ *.gem
data/.rubocop.yml CHANGED
@@ -1,22 +1,35 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
3
  AllCops:
4
- TargetRubyVersion: 2.3
4
+ NewCops: enable
5
+ TargetRubyVersion: 2.5
5
6
 
6
7
  Metrics/AbcSize:
7
- Max: 25
8
+ Max: 28
8
9
 
9
10
  # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
10
11
  # URISchemes: http, https
11
- Metrics/LineLength:
12
+ Layout/LineLength:
12
13
  Max: 140
13
14
 
14
15
  Metrics/MethodLength:
15
16
  Max: 40
16
17
 
18
+ Metrics/BlockLength:
19
+ Exclude:
20
+ - 'spec/**/*.rb'
21
+ - 'api_auth.gemspec'
22
+
17
23
  Naming/FileName:
18
24
  Exclude:
19
25
  - 'lib/api-auth.rb'
20
26
 
21
27
  Style/FrozenStringLiteralComment:
22
28
  Enabled: false
29
+
30
+ Style/StringLiterals:
31
+ Exclude:
32
+ - 'gemfiles/*.gemfile'
33
+
34
+ Lint/DuplicateBranch:
35
+ Enabled: false
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2018-10-22 20:30:52 +0700 using RuboCop version 0.59.2.
3
+ # on 2021-03-26 22:04:17 UTC using RuboCop version 1.12.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -8,7 +8,7 @@
8
8
 
9
9
  # Offense count: 1
10
10
  # Cop supports --auto-correct.
11
- # Configuration parameters: Include, TreatCommentsAsGroupSeparators.
11
+ # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
12
12
  # Include: **/*.gemspec
13
13
  Gemspec/OrderedDependencies:
14
14
  Exclude:
@@ -20,6 +20,13 @@ Lint/AssignmentInCondition:
20
20
  Exclude:
21
21
  - 'lib/api_auth/base.rb'
22
22
 
23
+ # Offense count: 4
24
+ # Configuration parameters: AllowedMethods.
25
+ # AllowedMethods: enums
26
+ Lint/ConstantDefinitionInBlock:
27
+ Exclude:
28
+ - 'spec/railtie_spec.rb'
29
+
23
30
  # Offense count: 9
24
31
  # Configuration parameters: CheckForMethodsWithNoSideEffects.
25
32
  Lint/Void:
@@ -35,19 +42,21 @@ Lint/Void:
35
42
  - 'lib/api_auth/request_drivers/rest_client.rb'
36
43
 
37
44
  # Offense count: 1
38
- # Configuration parameters: CountComments, ExcludedMethods.
39
- # ExcludedMethods: refine
45
+ # Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
46
+ Metrics/AbcSize:
47
+ Max: 28
48
+
49
+ # Offense count: 1
50
+ # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
51
+ # IgnoredMethods: refine
40
52
  Metrics/BlockLength:
41
53
  Max: 27
42
54
 
43
- # Offense count: 1
55
+ # Offense count: 2
56
+ # Configuration parameters: IgnoredMethods.
44
57
  Metrics/CyclomaticComplexity:
45
58
  Max: 15
46
59
 
47
- # Offense count: 1
48
- Metrics/PerceivedComplexity:
49
- Max: 8
50
-
51
60
  # Offense count: 10
52
61
  Naming/AccessorMethodName:
53
62
  Exclude:
@@ -64,29 +73,30 @@ Naming/AccessorMethodName:
64
73
 
65
74
  # Offense count: 3
66
75
  # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
67
- # AllowedNames: io, id, to, by, on, in, at, ip, db
68
- Naming/UncommunicativeMethodParamName:
76
+ # AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to
77
+ Naming/MethodParameterName:
69
78
  Exclude:
70
79
  - 'lib/api_auth/base.rb'
71
80
  - 'spec/railtie_spec.rb'
72
81
 
73
- # Offense count: 1
74
- # Configuration parameters: EnforcedStyle.
75
- # SupportedStyles: inline, group
76
- Style/AccessModifierDeclarations:
77
- Exclude:
78
- - 'lib/api_auth/headers.rb'
79
-
80
82
  # Offense count: 9
83
+ # Cop supports --auto-correct.
81
84
  Style/CommentedKeyword:
82
85
  Exclude:
83
86
  - 'lib/api_auth/base.rb'
84
87
  - 'lib/api_auth/railtie.rb'
85
88
 
86
- # Offense count: 4
89
+ # Offense count: 3
90
+ # Configuration parameters: AllowedConstants.
87
91
  Style/Documentation:
88
92
  Exclude:
89
93
  - 'spec/**/*'
90
94
  - 'test/**/*'
91
95
  - 'lib/api_auth/railtie.rb'
92
- - 'lib/api_auth/request_drivers/rest_client.rb'
96
+
97
+ # Offense count: 1
98
+ # Configuration parameters: AllowedMethods.
99
+ # AllowedMethods: respond_to_missing?
100
+ Style/OptionalBooleanParameter:
101
+ Exclude:
102
+ - 'lib/api_auth/railtie.rb'
data/Appraisals CHANGED
@@ -1,23 +1,17 @@
1
- appraise 'rails-5' do
2
- gem 'actionpack', '~> 5.0.2'
3
- gem 'activeresource', '~> 5.0.2'
4
- gem 'activesupport', '~> 5.0.2'
1
+ appraise 'rails-52' do
2
+ gem 'actionpack', '~> 5.2'
3
+ gem 'activeresource', '~> 5.1'
4
+ gem 'activesupport', '~> 5.2'
5
5
  end
6
6
 
7
- appraise 'rails-42' do
8
- gem 'actionpack', '~> 4.2.0'
9
- gem 'activeresource', '~> 4.0.0'
10
- gem 'activesupport', '~> 4.2.0'
7
+ appraise 'rails-60' do
8
+ gem 'actionpack', '~> 6.0'
9
+ gem 'activeresource', '~> 5.1'
10
+ gem 'activesupport', '~> 6.0'
11
11
  end
12
12
 
13
- appraise 'rails-41' do
14
- gem 'actionpack', '~> 4.1.0'
15
- gem 'activeresource', '~> 4.0.0'
16
- gem 'activesupport', '~> 4.1.0'
17
- end
18
-
19
- appraise 'rails-4' do
20
- gem 'actionpack', '~> 4.0.4'
21
- gem 'activeresource', '~> 4.0.0'
22
- gem 'activesupport', '~> 4.0.4'
13
+ appraise 'rails-61' do
14
+ gem 'actionpack', '~> 6.1'
15
+ gem 'activeresource', '~> 5.1'
16
+ gem 'activesupport', '~> 6.1'
23
17
  end
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ # 2.5.0 (2021-05-11)
2
+ - Add support for Ruby 3.0 (#194 fwininger)
3
+ - Add support for Rails 6.1 (#194 fwininger)
4
+ - Drop support for Ruby 2.4 (#193 fwininger)
5
+ - Drop support for Rails 5.0 (#194 fwininger)
6
+ - Drop support for Rails 5.1 (#194 fwininger)
7
+ - Fix Faraday warning: `WARNING: Faraday::Request#method is deprecated` (#191 fwininger)
8
+
9
+ # 2.4.1 (2020-06-23)
10
+ - Fix inadvertant ActiveSupport dependecy (#189 taylorthurlow)
11
+
12
+ # 2.4.0 (2020-05-05)
13
+ - Improved support for Rails 6.0 (#179 taylorthurlow, #177 fwininger)
14
+ - Added Ruby 2.6.0 support (#174 fwininger)
15
+ - README updates (#186 iranthau)
16
+
1
17
  # 2.3.1 (2018-11-06)
2
18
  - Fixed a regression in the http.rb driver (#173 tycooon)
3
19
 
data/Gemfile CHANGED
@@ -1,4 +1,2 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
-
4
- gem 'rubocop', platforms: %i[ruby_20 ruby_21 ruby_22 ruby_23 ruby_24]
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ApiAuth
2
2
 
3
- [![Build Status](https://travis-ci.org/mgomes/api_auth.svg?branch=master)](https://travis-ci.org/mgomes/api_auth)
3
+ [![Build Status](https://github.com/mgomes/api_auth/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/mgomes/api_auth/actions)
4
4
  [![Gem Version](https://badge.fury.io/rb/api-auth.svg)](https://badge.fury.io/rb/api-auth)
5
5
 
6
6
  Logins and passwords are for humans. Communication between applications need to
@@ -21,19 +21,35 @@ 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 URI and the timestamp. If content-type or
25
- content-MD5 are not present, then a blank string is used in their place. If the
26
- timestamp isn't present, a valid HTTP date is automatically added to the
27
- request. The canonical string is computed as follows:
24
+ `content-type`, `X-Authorization-Content-SHA256`, request path and the date/time stamp.
25
+ If `content-type` or `X-Authorization-Content-SHA256` are not present, then a blank
26
+ string is used in their place. If the timestamp isn't present, a valid HTTP date is
27
+ automatically added to the request. The canonical string is computed as follows:
28
28
 
29
- canonical_string = 'http method,content-type,content-MD5,request URI,timestamp'
29
+ ```ruby
30
+ canonical_string = "#{http method},#{content-type},#{X-Authorization-Content-SHA256},#{request URI},#{timestamp}"
31
+ ```
32
+
33
+ e.g.,
34
+
35
+ ```ruby
36
+ canonical_string = 'POST,application/json,,request_path,Tue, 30 May 2017 03:51:43 GMT'
37
+ ```
30
38
 
31
39
  2. This string is then used to create the signature which is a Base64 encoded
32
40
  SHA1 HMAC, using the client's private secret key.
33
41
 
34
42
  3. This signature is then added as the `Authorization` HTTP header in the form:
35
43
 
36
- Authorization = APIAuth 'client access id':'signature from step 2'
44
+ ```ruby
45
+ Authorization = APIAuth "#{client access id}:#{signature from step 2}"
46
+ ```
47
+
48
+ A cURL request would look like:
49
+
50
+ ```sh
51
+ 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`
52
+ ```
37
53
 
38
54
  5. On the server side, the SHA1 HMAC is computed in the same way using the
39
55
  request headers and the client's secret key, which is known to only
@@ -42,7 +58,6 @@ access id that was attached in the header. The access id can be any integer or
42
58
  string that uniquely identifies the client. The signed request expires after 15
43
59
  minutes in order to avoid replay attacks.
44
60
 
45
-
46
61
  ## References
47
62
 
48
63
  * [Hash functions](http://en.wikipedia.org/wiki/Cryptographic_hash_function)
@@ -52,7 +67,7 @@ minutes in order to avoid replay attacks.
52
67
 
53
68
  ## Requirement
54
69
 
55
- This gem require Ruby >= 2.3 and Rails >= 4.0 if you use rails.
70
+ This gem require Ruby >= 2.5 and Rails >= 5.1 if you use rails.
56
71
 
57
72
  For older version of Ruby or Rails, please use ApiAuth v2.1 and older.
58
73
 
@@ -63,7 +78,9 @@ For older version of Ruby or Rails, please use ApiAuth v2.1 and older.
63
78
  The gem doesn't have any dependencies outside of having a working OpenSSL
64
79
  configuration for your Ruby VM. To install:
65
80
 
66
- [sudo] gem install api-auth
81
+ ```sh
82
+ [sudo] gem install api-auth
83
+ ```
67
84
 
68
85
  Please note the dash in the name versus the underscore.
69
86
 
@@ -88,26 +105,30 @@ Here's a sample implementation of signing a request created with RestClient.
88
105
 
89
106
  Assuming you have a client access id and secret as follows:
90
107
 
91
- ``` ruby
92
- @access_id = "1044"
93
- @secret_key = ApiAuth.generate_secret_key
108
+ ```ruby
109
+ @access_id = "1044"
110
+ @secret_key = ApiAuth.generate_secret_key
94
111
  ```
95
112
 
96
113
  A typical RestClient PUT request may look like:
97
114
 
98
- ``` ruby
99
- headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
100
- 'Content-Type' => "text/plain",
101
- 'Date' => "Mon, 23 Jan 1984 03:29:56 GMT" }
102
- @request = RestClient::Request.new(:url => "/resource.xml?foo=bar&bar=foo",
103
- :headers => headers,
104
- :method => :put)
115
+ ```ruby
116
+ headers = { 'X-Authorization-Content-SHA256' => "dWiCWEMZWMxeKM8W8Yuh/TbI29Hw5xUSXZWXEJv63+Y=",
117
+ 'Content-Type' => "text/plain",
118
+ 'Date' => "Mon, 23 Jan 1984 03:29:56 GMT"
119
+ }
120
+
121
+ @request = RestClient::Request.new(
122
+ url: "/resource.xml?foo=bar&bar=foo",
123
+ headers: headers,
124
+ method: :put
125
+ )
105
126
  ```
106
127
 
107
128
  To sign that request, simply call the `sign!` method as follows:
108
129
 
109
- ``` ruby
110
- @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key)
130
+ ```ruby
131
+ @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key)
111
132
  ```
112
133
 
113
134
  The proper `Authorization` request header has now been added to that request
@@ -120,34 +141,38 @@ If you are signing a request for a driver that doesn't support automatic http
120
141
  method detection (like Curb or httpi), you can pass the http method as an option
121
142
  into the sign! method like so:
122
143
 
123
- ``` ruby
124
- @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key, :override_http_method => "PUT")
144
+ ```ruby
145
+ @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key, :override_http_method => "PUT")
125
146
  ```
126
147
 
127
148
  If you want to use another digest existing in `OpenSSL::Digest`,
128
149
  you can pass the http method as an option into the sign! method like so:
129
150
 
130
- ``` ruby
131
- @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key, :digest => 'sha256')
151
+ ```ruby
152
+ @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key, :digest => 'sha256')
132
153
  ```
133
154
 
134
155
  With the `digest` option, the `Authorization` header will be change from:
135
156
 
136
- Authorization = APIAuth 'client access id':'signature'
157
+ ```sh
158
+ Authorization = APIAuth 'client access id':'signature'
159
+ ```
137
160
 
138
161
  to:
139
162
 
140
- Authorization = APIAuth-HMAC-DIGEST_NAME 'client access id':'signature'
163
+ ```sh
164
+ Authorization = APIAuth-HMAC-DIGEST_NAME 'client access id':'signature'
165
+ ```
141
166
 
142
167
  ### ActiveResource Clients
143
168
 
144
169
  ApiAuth can transparently protect your ActiveResource communications with a
145
170
  single configuration line:
146
171
 
147
- ``` ruby
148
- class MyResource < ActiveResource::Base
149
- with_api_auth(access_id, secret_key)
150
- end
172
+ ```ruby
173
+ class MyResource < ActiveResource::Base
174
+ with_api_auth(access_id, secret_key)
175
+ end
151
176
  ```
152
177
 
153
178
  This will automatically sign all outgoing ActiveResource requests from your app.
@@ -157,7 +182,7 @@ This will automatically sign all outgoing ActiveResource requests from your app.
157
182
  ApiAuth also works with [Flexirest](https://github.com/andyjeffries/flexirest) (used to be ActiveRestClient, but that is now unsupported) in a very similar way.
158
183
  Simply add this configuration to your Flexirest initializer in your app and it will automatically sign all outgoing requests.
159
184
 
160
- ``` ruby
185
+ ```ruby
161
186
  Flexirest::Base.api_auth_credentials(@access_id, @secret_key)
162
187
  ```
163
188
 
@@ -168,27 +193,29 @@ clients as well as verifying incoming API requests.
168
193
 
169
194
  To generate a Base64 encoded API key for a client:
170
195
 
171
- ``` ruby
172
- ApiAuth.generate_secret_key
196
+ ```ruby
197
+ ApiAuth.generate_secret_key
173
198
  ```
174
199
 
175
200
  To validate whether or not a request is authentic:
176
201
 
177
- ``` ruby
178
- ApiAuth.authentic?(signed_request, secret_key)
202
+ ```ruby
203
+ ApiAuth.authentic?(signed_request, secret_key)
179
204
  ```
180
205
 
181
206
  The `authentic?` method uses the digest specified in the `Authorization` header.
182
207
  For example SHA256 for:
183
208
 
184
- Authorization = APIAuth-HMAC-SHA256 'client access id':'signature'
209
+ ```sh
210
+ Authorization = APIAuth-HMAC-SHA256 'client access id':'signature'
211
+ ```
185
212
 
186
213
  And by default SHA1 if the HMAC-DIGEST is not specified.
187
214
 
188
215
  If you want to force the usage of another digest method, you should pass it as an option parameter:
189
216
 
190
- ``` ruby
191
- ApiAuth.authentic?(signed_request, secret_key, :digest => 'sha256')
217
+ ```ruby
218
+ ApiAuth.authentic?(signed_request, secret_key, :digest => 'sha256')
192
219
  ```
193
220
 
194
221
  For security, requests dated older or newer than a certain timespan are considered inauthentic.
@@ -199,13 +226,13 @@ can't be dated into the far future.
199
226
  The default span is 15 minutes, but you can override this:
200
227
 
201
228
  ```ruby
202
- ApiAuth.authentic?(signed_request, secret_key, :clock_skew => 60) # or 1.minute in ActiveSupport
229
+ ApiAuth.authentic?(signed_request, secret_key, :clock_skew => 60) # or 1.minute in ActiveSupport
203
230
  ```
204
231
 
205
232
  If you want to sign custom headers, you can pass them as an array of strings in the options like so:
206
233
 
207
234
  ``` ruby
208
- ApiAuth.authentic?(signed_request, secret_key, headers_to_sign: %w[HTTP_HEADER_NAME])
235
+ ApiAuth.authentic?(signed_request, secret_key, headers_to_sign: %w[HTTP_HEADER_NAME])
209
236
  ```
210
237
 
211
238
  With the specified headers values being at the end of the canonical string in the same order.
@@ -216,7 +243,7 @@ In order to obtain the secret key for the client, you first need to look up the
216
243
  client's access_id. ApiAuth can pull that from the request headers for you:
217
244
 
218
245
  ``` ruby
219
- ApiAuth.access_id(signed_request)
246
+ ApiAuth.access_id(signed_request)
220
247
  ```
221
248
 
222
249
  Once you've looked up the client's record via the access id, you can then verify
@@ -228,12 +255,12 @@ Here's a sample method that can be used in a `before_action` if your server is a
228
255
  Rails app:
229
256
 
230
257
  ``` ruby
231
- before_action :api_authenticate
258
+ before_action :api_authenticate
232
259
 
233
- def api_authenticate
234
- @current_account = Account.find_by_access_id(ApiAuth.access_id(request))
235
- head(:unauthorized) unless @current_account && ApiAuth.authentic?(request, @current_account.secret_key)
236
- end
260
+ def api_authenticate
261
+ @current_account = Account.find_by_access_id(ApiAuth.access_id(request))
262
+ head(:unauthorized) unless @current_account && ApiAuth.authentic?(request, @current_account.secret_key)
263
+ end
237
264
  ```
238
265
 
239
266
  ## Development
@@ -246,11 +273,15 @@ To run the tests:
246
273
 
247
274
  Install the dependencies for a particular Rails version by specifying a gemfile in `gemfiles` directory:
248
275
 
249
- BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle install
276
+ ```sh
277
+ BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle install
278
+ ```
250
279
 
251
280
  Run the tests with those dependencies:
252
281
 
253
- BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle exec rake
282
+ ```sh
283
+ BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle exec rake
284
+ ```
254
285
 
255
286
  If you'd like to add support for additional HTTP clients, check out the already
256
287
  implemented drivers in `lib/api_auth/request_drivers` for reference. All of
@@ -260,6 +291,7 @@ the public methods for each driver are required to be implemented by your driver
260
291
 
261
292
  * [Mauricio Gomes](http://github.com/mgomes)
262
293
  * [Kevin Glowacz](http://github.com/kjg)
294
+ * [Florian Wininger](http://github.com/fwininger)
263
295
 
264
296
  ## Copyright
265
297
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.1
1
+ 2.5.1
data/api_auth.gemspec CHANGED
@@ -8,16 +8,21 @@ Gem::Specification.new do |s|
8
8
  s.version = File.read(File.join(File.dirname(__FILE__), 'VERSION'))
9
9
  s.authors = ['Mauricio Gomes']
10
10
  s.email = 'mauricio@edge14.com'
11
+ s.license = 'MIT'
11
12
 
12
- s.required_ruby_version = '>= 2.3.0'
13
+ s.metadata = {
14
+ 'rubygems_mfa_required' => 'true'
15
+ }
13
16
 
14
- s.add_development_dependency 'actionpack', '< 6.0', '> 4.0'
17
+ s.required_ruby_version = '>= 2.5.0'
18
+
19
+ s.add_development_dependency 'actionpack', '< 6.2', '> 5.0'
15
20
  s.add_development_dependency 'activeresource', '>= 4.0'
16
- s.add_development_dependency 'activesupport', '< 6.0', '> 4.0'
21
+ s.add_development_dependency 'activesupport', '< 6.2', '> 5.0'
17
22
  s.add_development_dependency 'amatch'
18
23
  s.add_development_dependency 'appraisal'
19
24
  s.add_development_dependency 'curb', '~> 0.8'
20
- s.add_development_dependency 'faraday', '>= 0.10'
25
+ s.add_development_dependency 'faraday', '>= 1.1.0'
21
26
  s.add_development_dependency 'http'
22
27
  s.add_development_dependency 'httpi'
23
28
  s.add_development_dependency 'multipart-post', '~> 2.0'
@@ -26,6 +31,8 @@ Gem::Specification.new do |s|
26
31
  s.add_development_dependency 'rest-client', '~> 2.0'
27
32
  s.add_development_dependency 'grape', '~> 1.1.0'
28
33
  s.add_development_dependency 'rspec', '~> 3.4'
34
+ s.add_development_dependency 'rexml'
35
+ s.add_development_dependency 'rubocop'
29
36
 
30
37
  s.files = `git ls-files`.split("\n")
31
38
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,9 +1,9 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source 'https://rubygems.org'
3
+ source "https://rubygems.org"
4
4
 
5
- gem 'actionpack', '~> 5.2.1'
6
- gem 'activeresource', '~> 5.0.0', git: 'https://github.com/rails/activeresource.git'
7
- gem 'activesupport', '~> 5.2.1'
5
+ gem "actionpack", "~> 5.2"
6
+ gem "activeresource", "~> 5.1"
7
+ gem "activesupport", "~> 5.2"
8
8
 
9
- gemspec path: '../'
9
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", "~> 6.0"
6
+ gem "activeresource", "~> 5.1"
7
+ gem "activesupport", "~> 6.0"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", "~> 6.1"
6
+ gem "activeresource", "~> 5.1"
7
+ gem "activesupport", "~> 6.1"
8
+
9
+ gemspec path: "../"
data/lib/api_auth/base.rb CHANGED
@@ -22,7 +22,7 @@ module ApiAuth
22
22
  def sign!(request, access_id, secret_key, options = {})
23
23
  options = { override_http_method: nil, digest: 'sha1' }.merge(options)
24
24
  headers = Headers.new(request)
25
- headers.calculate_md5
25
+ headers.calculate_hash
26
26
  headers.set_date
27
27
  headers.sign_header auth_header(headers, access_id, secret_key, options)
28
28
  end
@@ -39,7 +39,7 @@ module ApiAuth
39
39
  # 900 seconds is 15 minutes
40
40
  clock_skew = options.fetch(:clock_skew, 900)
41
41
 
42
- if headers.md5_mismatch?
42
+ if headers.content_hash_mismatch?
43
43
  false
44
44
  elsif !signatures_match?(headers, secret_key, options)
45
45
  false