Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ Lint/Void:
Metrics/CyclomaticComplexity:
Max: 16

# Offense count: 11
# Offense count: 12
Naming/AccessorMethodName:
Exclude:
- 'lib/api_auth/railtie.rb'
- 'lib/api_auth/request_drivers/action_controller.rb'
- 'lib/api_auth/request_drivers/curb.rb'
- 'lib/api_auth/request_drivers/excon.rb'
- 'lib/api_auth/request_drivers/faraday.rb'
- 'lib/api_auth/request_drivers/faraday_env.rb'
- 'lib/api_auth/request_drivers/grape_request.rb'
Expand Down
76 changes: 52 additions & 24 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
# 3.0.0 (Unreleased)

## Breaking Changes

- **Drop support for Ruby < 3.2** - Now requires Ruby 3.2, 3.3, or 3.4+
- **Drop support for Rails 6.x** - Now requires Rails 7.2+ or 8.0+
- **Remove deprecated Ruby 2.x compatibility code**

## New Features

- Add Excon HTTP client support with middleware (based on contribution by @stiak in PR #154)

## Improvements

- Update minimum Ruby version to 3.2
- Update minimum Rails version to 7.2
- Support Rails 8.0
- Remove explicit drb dependency (now provided by Rails 7.2+)
- Update development dependencies to latest versions:
- Excon ~> 0.100
- Faraday ~> 2.0
- HTTP ~> 5.0
- HTTPi ~> 4.0
Expand All @@ -19,6 +26,7 @@
- Rest-Client ~> 2.1

# 2.6.0 (2025-01-18)

- Add Faraday middleware support (#1322051 Frédéric Mangano)
- Add MD5 compatibility option in authentic? method (#a618e15 Samir ALI CHERIF)
- Add support for Ruby 3.1 and Rails 7.0 (#552cab0 fwininger)
Expand All @@ -30,13 +38,15 @@
- Add drb gem dependency (2.0.4-2.0.5) for Ruby 3.4+ compatibility while avoiding Ruby 2.6 conflicts

# 2.5.1 (2021-11-26)

- Add spec coverage for all content hashes (#202 fwininger)
- Require MFA for Rubygems (#203 fwininger)
- Integration with GitHub Actions
- Fix look up of `X-AUTHORIZATION-CONTENT-SHA256` header
- Adding license information to the gemspec

# 2.5.0 (2021-05-11)

- Add support for Ruby 3.0 (#194 fwininger)
- Add support for Rails 6.1 (#194 fwininger)
- Drop support for Ruby 2.4 (#193 fwininger)
Expand All @@ -45,23 +55,28 @@
- Fix Faraday warning: `WARNING: Faraday::Request#method is deprecated` (#191 fwininger)

# 2.4.1 (2020-06-23)

- Fix inadvertent ActiveSupport dependency (#189 taylorthurlow)

# 2.4.0 (2020-05-05)

- Improved support for Rails 6.0 (#179 taylorthurlow, #177 fwininger)
- Added Ruby 2.6.0 support (#174 fwininger)
- README updates (#186 iranthau)

# 2.3.1 (2018-11-06)

- Fixed a regression in the http.rb driver (#173 tycooon)

# 2.3.0 (2018-10-23)

- Added support for Grape API (#169 phuongnd08 & dunghuynh)
- Added option for specifying customer headers to sign via new `headers_to_sign`
argument (#170 fakenine)
- Fix tests and drop support for Ruby < 2.3 (#171 fwininger)

# 2.2.0 (2018-03-12)

- Drop support ruby 1.x, rails 2.x, rails 3.x (#141 fwininger)
- Add http.rb request driver (#164 tycooon)
- Fix POST and PUT requests in RestClient (#151 fwininger)
Expand All @@ -73,107 +88,120 @@
- Updates to the README (zfletch)

# 2.1.0 (2016-12-22)

- Fixed a NoMethodError that might occur when using the NetHttp Driver (#130 grahamkenville)
- More securely compare signatures in a way that prevents timing attacks (#56 leishman, #133 will0)
- Remove support for MD2 and MD4 hashing algorithms since they are insecure (#134 will0)
- Disallow requests that are too far in the future to limit the time available for a brute force signature guess (#119 fwininger)

# 2.0.1 (2016-07-25)

- Support of `api_auth_options` in ActiveResource integration (#102 fwininger)
- Replace use of `#blank?` with `#nil?` to not depend on ActiveSupport (#114 packrat386)
- Fix Auth header matching to not match invalid SHA algorithms (#115 packrat386)
- Replace `alias_method_chain` with `alias_method` in the railtie since
alias_method_chain is deprecated in Rails 5 (#118 mlarraz)

# 2.0.0 (2016-05-11)

- IMPORTANT: 2.0.0 is backwards incompatible with the default settings of v1.x
v2.0.0 always includes the http method in the canonical string.
You can use the upgrade strategy in v1.4.x and above to migrate to v2.0.0
without any down time. Please see the 1.4.0 release nodes for more info
- Added support for other digest algorithms like SHA-256 (#98 fwininger)

# 1.5.0 (2016-01-21)

- Added a sign_with_http_method configuration option to the ActiveResource
rails tie to correspond to passing the `:with_http_method => true` into
`ApiAuth.sign!`

# 1.4.1 (2016-01-04)

- Fixed an issue where getters wouldn't immediately have the correct value after
setting a date or content md5 in some of the request drivers (#91)

# 1.4.0 (2015-12-16)

## IMPORTANT SECURITY FIX (with backwards compatible fallback)

This version introduces a security fix. In previous versions, the canonical
string does not include the http method used to make the request, this means
two requests that would otherwise be identical (such as a GET and DELETE)
would have the same signature allowing for a MITM to swap one method for
another.
This version introduces a security fix. In previous versions, the canonical
string does not include the http method used to make the request, this means
two requests that would otherwise be identical (such as a GET and DELETE)
would have the same signature allowing for a MITM to swap one method for
another.

In ApiAuth v1.4 `ApiAuth.authentic?` will allow for requests signed using either
the canonical string WITH the http method, or WITHOUT it. `ApiAuth.sign!` will,
by default, still sign the request using the canonical string without the
method. However, passing in the `:with_http_method => true` option into
`ApiAuth.sign?` will cause the request to use the http method as part of the
canonical string.
In ApiAuth v1.4 `ApiAuth.authentic?` will allow for requests signed using either
the canonical string WITH the http method, or WITHOUT it. `ApiAuth.sign!` will,
by default, still sign the request using the canonical string without the
method. However, passing in the `:with_http_method => true` option into
`ApiAuth.sign?` will cause the request to use the http method as part of the
canonical string.

Example:
Example:

```ruby
ApiAuth.sign!(request, access_id, secret_key, {:with_http_method => true})
```
```ruby
ApiAuth.sign!(request, access_id, secret_key, {:with_http_method => true})
```

This allows for an upgrade strategy that would look like the following.
This allows for an upgrade strategy that would look like the following.

1. Update server side code to use ApiAuth v1.4
2. Update client side code to use ApiAuth v1.4
3. Update all client side code to sign with http method
4. Update server side code to ApiAuth v2.0 (removes the ability to authenticate without the http method)
5. Update all client side code to ApiAuth v2.0 (forces all signatures to contain the http method)
1. Update server side code to use ApiAuth v1.4
2. Update client side code to use ApiAuth v1.4
3. Update all client side code to sign with http method
4. Update server side code to ApiAuth v2.0 (removes the ability to authenticate without the http method)
5. Update all client side code to ApiAuth v2.0 (forces all signatures to contain the http method)

## Additional changes

- Performance enhancement: reduce allocation of Headers object (#81 pd)
- Performance enhancement: avoid reallocating static Regexps (#82 pd)
- Performance enhancement: reduce allocation of Headers object (#81 pd)
- Performance enhancement: avoid reallocating static Regexps (#82 pd)

# 1.3.2 (2015-08-28)

- Fixed a bug where some client adapters didn't treat an empty path as
"/" in the canonical string (#75 managr)

# 1.3.1 (2015-03-13)

- Fixed a bug where Faraday requests with no parameters were not signed
correctly (#65 nathanhoel)

# 1.3.0 (2015-03-12)

- Add a Faraday Request Driver (#64 nathanhoel)

# 1.2.6 (2014-10-01)

- Fix a bug in the ActionController request driver where calculated_md5 was
incorrect in certain scenarios. (#53 karl-petter)

# 1.2.5 (2014-09-09)

- Fix a bug where ApiAuth.authentic? would cause an ArgumentError when given a
request with an invalid date in the date header. It will now return false
instead. (#51 Nakort)

# 1.2.4 (2014-08-27)

- Fix a bug in the Net::HTTP request driver where the md5 isn't calculated
correctly when the content of the request is set with the `.body_stream`
method. (#49 adamcrown)

# 1.2.3 (2014-08-01)

- Update action controller request driver to fix a bug with OLD versions of
Rails using CGI

# 1.2.2 (2014-07-08)

- Fix Rest Client driver to account for the generated date when signing (cjeeky)

# 1.2.1 (2014-07-03)

- Fix Rest Client driver to account for the generated md5 when signing
(#45 cjeeky)
- Support for testing against Rails 4.1 (#42 awendt)
- Support for testing against Rails 4.1 (#42 awendt)
- Support all requests inheriting from Rack::Request (#43 mcls)

# 1.2.0 (2014-05-16)
Expand Down
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ added as a request driver.
* **Faraday** - Modular HTTP client library (with middleware support)
* **HTTPI** - Common interface for Ruby HTTP clients
* **HTTP** (http.rb) - Fast Ruby HTTP client with a chainable API
* **Excon** - Pure Ruby HTTP client for API interactions (with middleware support)
* **Grape** - REST-like API framework for Ruby (via Rack)
* **Rack::Request** - Generic Rack request objects

Expand Down Expand Up @@ -277,6 +278,52 @@ signed_request = ApiAuth.sign!(request, @access_id, @secret_key)

The order of middlewares is important. You should make sure api_auth is added after any middleware that modifies the request body or content-type header.

#### Excon

Excon can be used with ApiAuth in two ways - with middleware or by manually signing requests.

Using Excon middleware (recommended):

```ruby
require 'excon'
require 'excon/api_auth' # or require 'api_auth/middleware/excon'

# Configure Excon with ApiAuth credentials
Excon.defaults[:api_auth_access_id] = @access_id
Excon.defaults[:api_auth_secret_key] = @secret_key
Excon.defaults[:middlewares] << ApiAuth::Middleware::Excon

# All requests will be automatically signed
connection = Excon.new('https://api.example.com')
response = connection.post(
path: '/resource',
headers: { 'Content-Type' => 'application/json' },
body: '{"key": "value"}'
)
```

Manual signing (when you need more control):

```ruby
require 'excon'
require 'api_auth'

connection = Excon.new('https://api.example.com')
request_params = {
method: :post,
path: '/resource',
headers: { 'Content-Type' => 'application/json' },
body: '{"key": "value"}'
}

# Create a wrapper for signing
request = ApiAuth::Middleware::ExconRequestWrapper.new(request_params, '')
ApiAuth.sign!(request, @access_id, @secret_key)

# Execute the request with signed headers
response = connection.request(request_params)
```

### ActiveResource Clients

ApiAuth can transparently protect your ActiveResource communications with a
Expand Down
1 change: 1 addition & 0 deletions api_auth.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Gem::Specification.new do |s|
s.add_development_dependency 'amatch'
s.add_development_dependency 'appraisal'
s.add_development_dependency 'curb', '~> 1.0'
s.add_development_dependency 'excon', '~> 0.100'
s.add_development_dependency 'faraday', '~> 2.0'
s.add_development_dependency 'grape', '~> 2.0'
s.add_development_dependency 'http', '~> 5.0'
Expand Down
1 change: 1 addition & 0 deletions lib/api_auth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
require 'api_auth/request_drivers/faraday'
require 'api_auth/request_drivers/faraday_env'
require 'api_auth/request_drivers/http'
require 'api_auth/request_drivers/excon'

require 'api_auth/headers'
require 'api_auth/base'
Expand Down
Loading