api-auth 2.5.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 232d1199b2fd74328e77ba9dd3362789798585b3d88df7c6d4688cf843475190
4
- data.tar.gz: 879689b7f0b691212e0c14a80e087a041769241221b7a88f094c1003b29cfa9c
3
+ metadata.gz: b642f1c16d0ccca2a260e5440012a3d02fe3b333d3cb769a76e139ec97c39368
4
+ data.tar.gz: 5f68593348b4cbcf7b76250675c7bb355904b8f365129b8a57696e04fed5a802
5
5
  SHA512:
6
- metadata.gz: 2cb0fbdf6f5984f7334bdfa8a16309837c35b146eab39cd723203cd6861c9ce1e51d66fa2f73a3bb6a9490eaec2af0e3c73b34a03726d26360fc664aa7095f32
7
- data.tar.gz: 9a1e90785610686db8c1a84943d138f9528dd5ce28965774cfe3112ea74850d898694a7a2bd458ef513f0fd48db56015b8662c53ec78ec38d714080b6f59ed68
6
+ metadata.gz: f148aa229d78829b86af9772e962463866e3ad85653b9fc759494969c901717be7d9c6b11087f6873253777610d9dcf3b209189e0076249d72a5256dc2acf026
7
+ data.tar.gz: 6fab592a96c63ab8c52665c321c4291a5bd67fea0d366298a1c3efa82a6819e5a7434f2ed18c0cf48cac301cc219963fcdde831c237868e9a03cc5d09c3ae440
@@ -9,19 +9,23 @@ jobs:
9
9
  fail-fast: true
10
10
  matrix:
11
11
  ruby-version:
12
- - 2.5
13
12
  - 2.6
14
13
  - 2.7
15
14
  - 3.0
15
+ - 3.1
16
16
  gemfile:
17
- - rails_52.gemfile
18
17
  - rails_60.gemfile
19
18
  - rails_61.gemfile
19
+ - rails_70.gemfile
20
20
  exclude:
21
- - ruby-version: [ 2.6, 2.7, 3.0 ]
22
- gemfile: rails_52.gemfile
23
21
  - ruby-version: 3.0
24
22
  gemfile: rails_60.gemfile
23
+ - ruby-version: 3.1
24
+ gemfile: rails_60.gemfile
25
+ - ruby-version: 2.6
26
+ gemfile: rails_70.gemfile
27
+ - ruby-version: 2.7
28
+ gemfile: rails_70.gemfile
25
29
  steps:
26
30
  - name: Install packages required for `curb` gem
27
31
  run: |
@@ -57,7 +61,7 @@ jobs:
57
61
  - name: Install Ruby
58
62
  uses: ruby/setup-ruby@v1
59
63
  with:
60
- ruby-version: 3.0
64
+ ruby-version: 3.1
61
65
  bundler-cache: true
62
66
 
63
67
  - name: Install required gems
data/.rubocop.yml CHANGED
@@ -2,7 +2,7 @@ inherit_from: .rubocop_todo.yml
2
2
 
3
3
  AllCops:
4
4
  NewCops: enable
5
- TargetRubyVersion: 2.5
5
+ TargetRubyVersion: 2.6
6
6
 
7
7
  Metrics/AbcSize:
8
8
  Max: 28
@@ -33,3 +33,7 @@ Style/StringLiterals:
33
33
 
34
34
  Lint/DuplicateBranch:
35
35
  Enabled: false
36
+
37
+ # Development dependencies in gemspec is valid for gems
38
+ Gemspec/DevelopmentDependencies:
39
+ Enabled: false
data/.rubocop_todo.yml CHANGED
@@ -1,19 +1,11 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2021-03-26 22:04:17 UTC using RuboCop version 1.12.0.
3
+ # on 2022-08-03 07:19:11 UTC using RuboCop version 1.32.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
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 1
10
- # Cop supports --auto-correct.
11
- # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
12
- # Include: **/*.gemspec
13
- Gemspec/OrderedDependencies:
14
- Exclude:
15
- - 'api_auth.gemspec'
16
-
17
9
  # Offense count: 1
18
10
  # Configuration parameters: AllowSafeAssignment.
19
11
  Lint/AssignmentInCondition:
@@ -41,29 +33,19 @@ Lint/Void:
41
33
  - 'lib/api_auth/request_drivers/rack.rb'
42
34
  - 'lib/api_auth/request_drivers/rest_client.rb'
43
35
 
44
- # Offense count: 1
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
52
- Metrics/BlockLength:
53
- Max: 27
54
-
55
36
  # Offense count: 2
56
37
  # Configuration parameters: IgnoredMethods.
57
38
  Metrics/CyclomaticComplexity:
58
- Max: 15
39
+ Max: 16
59
40
 
60
- # Offense count: 10
41
+ # Offense count: 11
61
42
  Naming/AccessorMethodName:
62
43
  Exclude:
63
44
  - 'lib/api_auth/railtie.rb'
64
45
  - 'lib/api_auth/request_drivers/action_controller.rb'
65
46
  - 'lib/api_auth/request_drivers/curb.rb'
66
47
  - 'lib/api_auth/request_drivers/faraday.rb'
48
+ - 'lib/api_auth/request_drivers/faraday_env.rb'
67
49
  - 'lib/api_auth/request_drivers/grape_request.rb'
68
50
  - 'lib/api_auth/request_drivers/http.rb'
69
51
  - 'lib/api_auth/request_drivers/httpi.rb'
@@ -79,20 +61,14 @@ Naming/MethodParameterName:
79
61
  - 'lib/api_auth/base.rb'
80
62
  - 'spec/railtie_spec.rb'
81
63
 
82
- # Offense count: 9
83
- # Cop supports --auto-correct.
84
- Style/CommentedKeyword:
85
- Exclude:
86
- - 'lib/api_auth/base.rb'
87
- - 'lib/api_auth/railtie.rb'
88
-
89
- # Offense count: 3
64
+ # Offense count: 4
90
65
  # Configuration parameters: AllowedConstants.
91
66
  Style/Documentation:
92
67
  Exclude:
93
68
  - 'spec/**/*'
94
69
  - 'test/**/*'
95
70
  - 'lib/api_auth/railtie.rb'
71
+ - 'lib/api_auth/request_drivers/rest_client.rb'
96
72
 
97
73
  # Offense count: 1
98
74
  # Configuration parameters: AllowedMethods.
@@ -100,3 +76,8 @@ Style/Documentation:
100
76
  Style/OptionalBooleanParameter:
101
77
  Exclude:
102
78
  - 'lib/api_auth/railtie.rb'
79
+
80
+ # Offense count: 1
81
+ Lint/UselessConstantScoping:
82
+ Exclude:
83
+ - 'lib/api_auth/base.rb'
data/Appraisals CHANGED
@@ -1,9 +1,3 @@
1
- appraise 'rails-52' do
2
- gem 'actionpack', '~> 5.2'
3
- gem 'activeresource', '~> 5.1'
4
- gem 'activesupport', '~> 5.2'
5
- end
6
-
7
1
  appraise 'rails-60' do
8
2
  gem 'actionpack', '~> 6.0'
9
3
  gem 'activeresource', '~> 5.1'
@@ -15,3 +9,9 @@ appraise 'rails-61' do
15
9
  gem 'activeresource', '~> 5.1'
16
10
  gem 'activesupport', '~> 6.1'
17
11
  end
12
+
13
+ appraise 'rails-70' do
14
+ gem 'actionpack', '~> 7.0'
15
+ gem 'activeresource', '~> 6.0'
16
+ gem 'activesupport', '~> 7.0'
17
+ end
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ # 2.6.0 (2025-01-18)
2
+ - Add Faraday middleware support (#1322051 Frédéric Mangano)
3
+ - Add MD5 compatibility option in authentic? method (#a618e15 Samir ALI CHERIF)
4
+ - Add support for Ruby 3.1 and Rails 7.0 (#552cab0 fwininger)
5
+ - Drop support for Rails 5 and Ruby 2.5 (#552cab0 fwininger)
6
+ - Fix HTTPS URL handling (#c734a88 fwininger)
7
+ - Update Grape to v2.0+ for Rails 7/Rack 3 compatibility
8
+ - Update Rubocop to v1.50+ and Curb to v1.0+ for Ruby 3.x compatibility
9
+ - Fix Ruby 2.6 compatibility with Rails 6.x (Logger loading issue)
10
+ - Add drb gem dependency (2.0.4-2.0.5) for Ruby 3.4+ compatibility while avoiding Ruby 2.6 conflicts
11
+
12
+ # 2.5.1 (2021-11-26)
13
+ - Add spec coverage for all content hashes (#202 fwininger)
14
+ - Require MFA for Rubygems (#203 fwininger)
15
+ - Integration with GitHub Actions
16
+ - Fix look up of `X-AUTHORIZATION-CONTENT-SHA256` header
17
+ - Adding license information to the gemspec
18
+
1
19
  # 2.5.0 (2021-05-11)
2
20
  - Add support for Ruby 3.0 (#194 fwininger)
3
21
  - Add support for Rails 6.1 (#194 fwininger)
data/README.md CHANGED
@@ -7,7 +7,7 @@ Logins and passwords are for humans. Communication between applications need to
7
7
  be protected through different means.
8
8
 
9
9
  ApiAuth is a Ruby gem designed to be used both in your client and server
10
- HTTP-based applications. It implements the same authentication methods (HMAC-SHA1)
10
+ HTTP-based applications. It implements the same authentication methods (HMAC-SHA2)
11
11
  used by Amazon Web Services.
12
12
 
13
13
  The gem will sign your requests on the client side and authenticate that
@@ -48,10 +48,10 @@ Authorization = APIAuth "#{client access id}:#{signature from step 2}"
48
48
  A cURL request would look like:
49
49
 
50
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`
51
+ curl -X POST --header 'Content-Type: application/json' --header "Date: Tue, 30 May 2017 03:51:43 GMT" --header "Authorization: ${AUTHORIZATION}" https://my-app.com/request_path`
52
52
  ```
53
53
 
54
- 5. On the server side, the SHA1 HMAC is computed in the same way using the
54
+ 5. On the server side, the SHA2 HMAC is computed in the same way using the
55
55
  request headers and the client's secret key, which is known to only
56
56
  the client and the server but can be looked up on the server using the client's
57
57
  access id that was attached in the header. The access id can be any integer or
@@ -60,18 +60,14 @@ minutes in order to avoid replay attacks.
60
60
 
61
61
  ## References
62
62
 
63
- * [Hash functions](http://en.wikipedia.org/wiki/Cryptographic_hash_function)
64
- * [SHA-1 Hash function](http://en.wikipedia.org/wiki/SHA-1)
65
- * [HMAC algorithm](http://en.wikipedia.org/wiki/HMAC)
66
- * [RFC 2104 (HMAC)](http://tools.ietf.org/html/rfc2104)
63
+ * [Hash functions](https://en.wikipedia.org/wiki/Cryptographic_hash_function)
64
+ * [SHA-2 Hash function](https://en.wikipedia.org/wiki/SHA-2)
65
+ * [HMAC algorithm](https://en.wikipedia.org/wiki/HMAC)
66
+ * [RFC 2104 (HMAC)](https://tools.ietf.org/html/rfc2104)
67
67
 
68
68
  ## Requirement
69
69
 
70
- This gem require Ruby >= 2.5 and Rails >= 5.1 if you use rails.
71
-
72
- For older version of Ruby or Rails, please use ApiAuth v2.1 and older.
73
-
74
- **IMPORTANT: v2.0.0 is backwards incompatible with the default settings of v1.x to address a security vulnerability. See [CHANGELOG.md](/CHANGELOG.md) for security update information.**
70
+ This gem require Ruby >= 2.6 and Rails >= 6.0 if you use rails.
75
71
 
76
72
  ## Install
77
73
 
@@ -186,6 +182,19 @@ Simply add this configuration to your Flexirest initializer in your app and it w
186
182
  Flexirest::Base.api_auth_credentials(@access_id, @secret_key)
187
183
  ```
188
184
 
185
+ ### Faraday
186
+
187
+ ApiAuth provides a middleware for adding authentication to a Faraday connection:
188
+
189
+ ```ruby
190
+ require 'faraday/api_auth'
191
+ Faraday.new do |f|
192
+ f.request :api_auth, @access_id, @secret_key
193
+ end
194
+ ```
195
+
196
+ The order of middlewares is important. You should make sure api_auth is last.
197
+
189
198
  ## Server
190
199
 
191
200
  ApiAuth provides some built in methods to help you generate API keys for your
@@ -289,9 +298,9 @@ the public methods for each driver are required to be implemented by your driver
289
298
 
290
299
  ## Authors
291
300
 
292
- * [Mauricio Gomes](http://github.com/mgomes)
293
- * [Kevin Glowacz](http://github.com/kjg)
294
- * [Florian Wininger](http://github.com/fwininger)
301
+ * [Mauricio Gomes](https://github.com/mgomes)
302
+ * [Kevin Glowacz](https://github.com/kjg)
303
+ * [Florian Wininger](https://github.com/fwininger)
295
304
 
296
305
  ## Copyright
297
306
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.5.1
1
+ 2.6.0
data/api_auth.gemspec CHANGED
@@ -14,28 +14,29 @@ Gem::Specification.new do |s|
14
14
  'rubygems_mfa_required' => 'true'
15
15
  }
16
16
 
17
- s.required_ruby_version = '>= 2.5.0'
17
+ s.required_ruby_version = '>= 2.6.0'
18
18
 
19
- s.add_development_dependency 'actionpack', '< 6.2', '> 5.0'
19
+ s.add_development_dependency 'actionpack', '>= 6.0'
20
20
  s.add_development_dependency 'activeresource', '>= 4.0'
21
- s.add_development_dependency 'activesupport', '< 6.2', '> 5.0'
21
+ s.add_development_dependency 'activesupport', '>= 6.0'
22
22
  s.add_development_dependency 'amatch'
23
23
  s.add_development_dependency 'appraisal'
24
- s.add_development_dependency 'curb', '~> 0.8'
24
+ s.add_development_dependency 'curb', '~> 1.0'
25
+ # DRb is required for Ruby 3.4+ but must avoid 2.0.6 which breaks Ruby 2.6
26
+ s.add_development_dependency 'drb', '>= 2.0.4', '< 2.0.6'
25
27
  s.add_development_dependency 'faraday', '>= 1.1.0'
28
+ s.add_development_dependency 'grape', '~> 2.0'
26
29
  s.add_development_dependency 'http'
27
30
  s.add_development_dependency 'httpi'
28
31
  s.add_development_dependency 'multipart-post', '~> 2.0'
29
32
  s.add_development_dependency 'pry'
30
33
  s.add_development_dependency 'rake'
31
34
  s.add_development_dependency 'rest-client', '~> 2.0'
32
- s.add_development_dependency 'grape', '~> 1.1.0'
33
- s.add_development_dependency 'rspec', '~> 3.4'
34
35
  s.add_development_dependency 'rexml'
35
- s.add_development_dependency 'rubocop'
36
+ s.add_development_dependency 'rspec', '~> 3.4'
37
+ s.add_development_dependency 'rubocop', '~> 1.50'
36
38
 
37
39
  s.files = `git ls-files`.split("\n")
38
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
39
40
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
40
41
  s.require_paths = ['lib']
41
42
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "actionpack", "~> 5.2"
6
- gem "activeresource", "~> 5.1"
7
- gem "activesupport", "~> 5.2"
5
+ gem "actionpack", "~> 7.0"
6
+ gem "activeresource", "~> 6.0"
7
+ gem "activesupport", "~> 7.0"
8
8
 
9
9
  gemspec path: "../"
data/lib/api_auth/base.rb CHANGED
@@ -32,9 +32,9 @@ module ApiAuth
32
32
  def authentic?(request, secret_key, options = {})
33
33
  return false if secret_key.nil?
34
34
 
35
- options = { override_http_method: nil }.merge(options)
35
+ options = { override_http_method: nil, authorize_md5: false }.merge(options)
36
36
 
37
- headers = Headers.new(request)
37
+ headers = Headers.new(request, authorize_md5: options[:authorize_md5])
38
38
 
39
39
  # 900 seconds is 15 minutes
40
40
  clock_skew = options.fetch(:clock_skew, 900)
@@ -118,5 +118,5 @@ module ApiAuth
118
118
  def parse_auth_header(auth_header)
119
119
  AUTH_HEADER_PATTERN.match(auth_header)
120
120
  end
121
- end # class methods
122
- end # ApiAuth
121
+ end
122
+ end
@@ -3,13 +3,13 @@ module ApiAuth
3
3
  class Headers
4
4
  include RequestDrivers
5
5
 
6
- def initialize(request)
6
+ def initialize(request, authorize_md5: false)
7
7
  @original_request = request
8
- @request = initialize_request_driver(request)
8
+ @request = initialize_request_driver(request, authorize_md5: authorize_md5)
9
9
  true
10
10
  end
11
11
 
12
- def initialize_request_driver(request)
12
+ def initialize_request_driver(request, authorize_md5: false)
13
13
  new_request =
14
14
  case request.class.to_s
15
15
  when /Net::HTTP/
@@ -29,13 +29,15 @@ module ApiAuth
29
29
  when /Grape::Request/
30
30
  GrapeRequest.new(request)
31
31
  when /ActionDispatch::Request/
32
- ActionDispatchRequest.new(request)
32
+ ActionDispatchRequest.new(request, authorize_md5: authorize_md5)
33
33
  when /ActionController::CgiRequest/
34
34
  ActionControllerRequest.new(request)
35
35
  when /HTTPI::Request/
36
36
  HttpiRequest.new(request)
37
37
  when /Faraday::Request/
38
38
  FaradayRequest.new(request)
39
+ when /Faraday::Env/
40
+ FaradayEnv.new(request)
39
41
  when /HTTP::Request/
40
42
  HttpRequest.new(request)
41
43
  end
@@ -8,6 +8,10 @@ module ApiAuth
8
8
  Digest::SHA256.base64digest(string)
9
9
  end
10
10
 
11
+ def md5_base64digest(string)
12
+ Digest::MD5.base64digest(string)
13
+ end
14
+
11
15
  # Capitalizes the keys of a hash
12
16
  def capitalize_keys(hsh)
13
17
  capitalized_hash = {}
@@ -18,7 +18,7 @@ module ApiAuth
18
18
  ActionController::Base.include(ControllerMethods::InstanceMethods)
19
19
  end
20
20
  end
21
- end # ControllerMethods
21
+ end
22
22
 
23
23
  module ActiveResourceExtension # :nodoc:
24
24
  module ActiveResourceApiAuth # :nodoc:
@@ -51,11 +51,11 @@ module ApiAuth
51
51
  c.api_auth_options = api_auth_options
52
52
  c
53
53
  end
54
- end # class methods
54
+ end
55
55
 
56
56
  module InstanceMethods
57
57
  end
58
- end # BaseApiAuth
58
+ end
59
59
 
60
60
  module Connection
61
61
  def self.included(base)
@@ -82,7 +82,7 @@ module ApiAuth
82
82
 
83
83
  request_without_auth(method, path, *arguments)
84
84
  end
85
- end # Connection
85
+ end
86
86
 
87
87
  if defined?(ActiveSupport)
88
88
  ActiveSupport.on_load(:active_resource) do
@@ -90,6 +90,6 @@ module ApiAuth
90
90
  ActiveResource::Connection.include(Connection)
91
91
  end
92
92
  end
93
- end # ActiveResourceExtension
94
- end # Rails
95
- end # ApiAuth
93
+ end
94
+ end
95
+ end
@@ -3,8 +3,9 @@ module ApiAuth
3
3
  class ActionControllerRequest # :nodoc:
4
4
  include ApiAuth::Helpers
5
5
 
6
- def initialize(request)
6
+ def initialize(request, authorize_md5: false)
7
7
  @request = request
8
+ @authorize_md5 = authorize_md5
8
9
  fetch_headers
9
10
  true
10
11
  end
@@ -17,7 +18,9 @@ module ApiAuth
17
18
 
18
19
  def calculated_hash
19
20
  body = @request.raw_post
20
- sha256_base64digest(body)
21
+ hashes = [sha256_base64digest(body)]
22
+ hashes << md5_base64digest(body) if @authorize_md5
23
+ hashes
21
24
  end
22
25
 
23
26
  def populate_content_hash
@@ -29,7 +32,7 @@ module ApiAuth
29
32
 
30
33
  def content_hash_mismatch?
31
34
  if @request.put? || @request.post?
32
- calculated_hash != content_hash
35
+ !calculated_hash.include?(content_hash)
33
36
  else
34
37
  false
35
38
  end
@@ -48,7 +51,9 @@ module ApiAuth
48
51
  end
49
52
 
50
53
  def content_hash
51
- find_header(%w[X-AUTHORIZATION-CONTENT-SHA256 X_AUTHORIZATION_CONTENT_SHA256 HTTP_X_AUTHORIZATION_CONTENT_SHA256])
54
+ headers = %w[X-AUTHORIZATION-CONTENT-SHA256 X_AUTHORIZATION_CONTENT_SHA256 HTTP_X_AUTHORIZATION_CONTENT_SHA256]
55
+ headers += %w[CONTENT-MD5 CONTENT_MD5 HTTP_CONTENT_MD5] if @authorize_md5
56
+ find_header(headers)
52
57
  end
53
58
 
54
59
  def original_uri
@@ -0,0 +1,102 @@
1
+ module ApiAuth
2
+ module RequestDrivers # :nodoc:
3
+ # Internally, Faraday uses the class Faraday::Env to represent requests. The class is not meant
4
+ # to be directly exposed to users, but this is what Faraday middlewares work with. See
5
+ # <https://lostisland.github.io/faraday/middleware/>.
6
+ class FaradayEnv
7
+ include ApiAuth::Helpers
8
+
9
+ def initialize(env)
10
+ @env = env
11
+ end
12
+
13
+ def set_auth_header(header)
14
+ @env.request_headers['Authorization'] = header
15
+ @env
16
+ end
17
+
18
+ def calculated_hash
19
+ sha256_base64digest(body)
20
+ end
21
+
22
+ def populate_content_hash
23
+ return unless %w[POST PUT PATCH].include?(http_method)
24
+
25
+ @env.request_headers['X-Authorization-Content-SHA256'] = calculated_hash
26
+ end
27
+
28
+ def content_hash_mismatch?
29
+ if %w[POST PUT PATCH].include?(http_method)
30
+ calculated_hash != content_hash
31
+ else
32
+ false
33
+ end
34
+ end
35
+
36
+ def http_method
37
+ @env.method.to_s.upcase
38
+ end
39
+
40
+ def content_type
41
+ type = find_header(%w[CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE])
42
+
43
+ # When sending a body-less POST request, the Content-Type is set at the last minute by the
44
+ # Net::HTTP adapter, which states in the documentation for Net::HTTP#post:
45
+ #
46
+ # > You should set Content-Type: header field for POST. If no Content-Type: field given,
47
+ # > this method uses “application/x-www-form-urlencoded” by default.
48
+ #
49
+ # The same applies to PATCH and PUT. Hopefully the other HTTP adapters behave similarly.
50
+ #
51
+ type ||= 'application/x-www-form-urlencoded' if %w[POST PATCH PUT].include?(http_method)
52
+
53
+ type
54
+ end
55
+
56
+ def content_hash
57
+ find_header(%w[X-AUTHORIZATION-CONTENT-SHA256])
58
+ end
59
+
60
+ def original_uri
61
+ find_header(%w[X-ORIGINAL-URI X_ORIGINAL_URI HTTP_X_ORIGINAL_URI])
62
+ end
63
+
64
+ def request_uri
65
+ @env.url.request_uri
66
+ end
67
+
68
+ def set_date
69
+ @env.request_headers['Date'] = Time.now.utc.httpdate
70
+ end
71
+
72
+ def timestamp
73
+ find_header(%w[DATE HTTP_DATE])
74
+ end
75
+
76
+ def authorization_header
77
+ find_header(%w[Authorization AUTHORIZATION HTTP_AUTHORIZATION])
78
+ end
79
+
80
+ def body
81
+ body_source = @env.request_body
82
+ if body_source.respond_to?(:read)
83
+ result = body_source.read
84
+ body_source.rewind
85
+ result
86
+ else
87
+ body_source.to_s
88
+ end
89
+ end
90
+
91
+ def fetch_headers
92
+ capitalize_keys @env.request_headers
93
+ end
94
+
95
+ private
96
+
97
+ def find_header(keys)
98
+ keys.map { |key| @env.request_headers[key] }.compact.first
99
+ end
100
+ end
101
+ end
102
+ end
data/lib/api_auth.rb CHANGED
@@ -14,6 +14,7 @@ require 'api_auth/request_drivers/action_dispatch'
14
14
  require 'api_auth/request_drivers/rack'
15
15
  require 'api_auth/request_drivers/httpi'
16
16
  require 'api_auth/request_drivers/faraday'
17
+ require 'api_auth/request_drivers/faraday_env'
17
18
  require 'api_auth/request_drivers/http'
18
19
 
19
20
  require 'api_auth/headers'
@@ -0,0 +1,35 @@
1
+ require 'api_auth'
2
+
3
+ module Faraday
4
+ module ApiAuth
5
+ # Request middleware for Faraday. It takes the same arguments as ApiAuth.sign!.
6
+ #
7
+ # You will usually need to include it after the other middlewares since ApiAuth needs to hash
8
+ # the final request.
9
+ #
10
+ # Usage:
11
+ #
12
+ # ```ruby
13
+ # require 'faraday/api_auth'
14
+ #
15
+ # conn = Faraday.new do |f|
16
+ # f.request :api_auth, access_id, secret_key
17
+ # # Alternatively:
18
+ # # f.use Faraday::ApiAuth::Middleware, access_id, secret_key
19
+ # end
20
+ # ```
21
+ #
22
+ class Middleware < Faraday::Middleware
23
+ def initialize(app, access_id, secret_key, options = {})
24
+ super(app)
25
+ @access_id = access_id
26
+ @secret_key = secret_key
27
+ @options = options
28
+ end
29
+
30
+ def on_request(env)
31
+ ::ApiAuth.sign!(env, @access_id, @secret_key, @options)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+ require_relative 'api_auth/middleware'
2
+
3
+ module Faraday
4
+ # Integrate ApiAuth into Faraday.
5
+ module ApiAuth
6
+ Faraday::Request.register_middleware(api_auth: Middleware)
7
+ end
8
+ end
@@ -24,7 +24,7 @@ describe 'ApiAuth' do
24
24
  end
25
25
 
26
26
  describe '.sign!' do
27
- let(:request) { RestClient::Request.new(url: 'http://google.com', method: :get) }
27
+ let(:request) { RestClient::Request.new(url: 'https://google.com', method: :get) }
28
28
  let(:headers) { ApiAuth::Headers.new(request) }
29
29
 
30
30
  it 'generates date header before signing' do
@@ -182,7 +182,7 @@ describe 'ApiAuth' do
182
182
  context 'normal APIAuth Auth header' do
183
183
  let(:request) do
184
184
  RestClient::Request.new(
185
- url: 'http://google.com',
185
+ url: 'https://google.com',
186
186
  method: :get,
187
187
  headers: { authorization: 'APIAuth 1044:aGVsbG8gd29ybGQ=' }
188
188
  )
@@ -196,7 +196,7 @@ describe 'ApiAuth' do
196
196
  context 'Corporate prefixed APIAuth header' do
197
197
  let(:request) do
198
198
  RestClient::Request.new(
199
- url: 'http://google.com',
199
+ url: 'https://google.com',
200
200
  method: :get,
201
201
  headers: { authorization: 'Corporate APIAuth 1044:aGVsbG8gd29ybGQ=' }
202
202
  )