Skip to content

Commit 7c822df

Browse files
authored
Revert "Strip query params" (#223)
* Revert "Strip query params (#222)" This reverts commit 434b0e9. * an empty commit
1 parent 434b0e9 commit 7c822df

File tree

8 files changed

+18
-86
lines changed

8 files changed

+18
-86
lines changed

CHANGELOG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
- **Drop support for Ruby < 3.2** - Now requires Ruby 3.2, 3.3, or 3.4+
66
- **Drop support for Rails 6.x** - Now requires Rails 7.2+ or 8.0+
77
- **Remove deprecated Ruby 2.x compatibility code**
8-
- **Canonical string no longer includes query parameters** – signatures now use only the request path. During a staged rollout you can temporarily accept legacy query-aware signatures by setting `ApiAuth.legacy_query_params_compatibility = true`.
98

109
## New Features
1110

@@ -31,8 +30,8 @@
3130
- RSpec ~> 3.13
3231
- Rake ~> 13.0
3332
- Rest-Client ~> 2.1
34-
- Typhoeus ~> 1.4
3533
- Remove implicit ActiveSupport requirement from runtime
34+
- Typhoeus ~> 1.4
3635

3736
# 2.6.0 (2025-01-18)
3837

README.md

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ automatically added to the request. The canonical string is computed as follows:
3030
canonical_string = "#{http method},#{content-type},#{X-Authorization-Content-SHA256},#{request URI},#{timestamp}"
3131
```
3232

33-
> **Note:** As of v3.0 the "request URI" component above is just the path (query parameters are excluded) so signatures remain stable even when intermediaries rewrite a query string.
34-
3533
e.g.,
3634

3735
```ruby
@@ -60,16 +58,6 @@ access id that was attached in the header. The access id can be any integer or
6058
string that uniquely identifies the client. The signed request expires after 15
6159
minutes in order to avoid replay attacks.
6260

63-
### Legacy query parameter compatibility
64-
65-
Versions prior to 3.0 included the query string inside the canonical request URI. If you have to roll out the 3.0 change gradually across multiple services, you can temporarily enable support for legacy signatures on the server side:
66-
67-
```ruby
68-
ApiAuth.legacy_query_params_compatibility = true
69-
```
70-
71-
With the flag disabled (the default) only the path segment is considered part of the canonical string.
72-
7361
## References
7462

7563
* [Hash functions](https://en.wikipedia.org/wiki/Cryptographic_hash_function)

lib/api_auth/base.rb

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ module ApiAuth
1010
class << self
1111
include Helpers
1212

13-
attr_writer :legacy_query_params_compatibility
14-
15-
def legacy_query_params_compatibility?
16-
!!@legacy_query_params_compatibility
17-
end
18-
1913
# Signs an HTTP request using the client's access id and secret key.
2014
# Returns the HTTP request object with the modified headers.
2115
#
@@ -96,16 +90,9 @@ def signatures_match?(headers, secret_key, options)
9690
options = { digest: digest }.merge(options)
9791

9892
header_sig = match_data[3]
99-
calculated_sig = hmac_signature(headers, secret_key, options, include_query: false)
100-
101-
return true if secure_equals?(header_sig, calculated_sig, secret_key)
93+
calculated_sig = hmac_signature(headers, secret_key, options)
10294

103-
if legacy_query_params_compatibility?
104-
legacy_sig = hmac_signature(headers, secret_key, options, include_query: true)
105-
return true if secure_equals?(header_sig, legacy_sig, secret_key)
106-
end
107-
108-
false
95+
secure_equals?(header_sig, calculated_sig, secret_key)
10996
end
11097

11198
def secure_equals?(m1, m2, key)
@@ -117,15 +104,15 @@ def sha1_hmac(key, message)
117104
OpenSSL::HMAC.digest(digest, key, message)
118105
end
119106

120-
def hmac_signature(headers, secret_key, options, include_query: false)
121-
canonical_string = headers.canonical_string(options[:override_http_method], options[:headers_to_sign], include_query: include_query)
107+
def hmac_signature(headers, secret_key, options)
108+
canonical_string = headers.canonical_string(options[:override_http_method], options[:headers_to_sign])
122109
digest = OpenSSL::Digest.new(options[:digest])
123110
b64_encode(OpenSSL::HMAC.digest(digest, secret_key, canonical_string))
124111
end
125112

126113
def auth_header(headers, access_id, secret_key, options)
127114
hmac_string = "-HMAC-#{options[:digest].upcase}" unless options[:digest] == 'sha1'
128-
"APIAuth#{hmac_string} #{access_id}:#{hmac_signature(headers, secret_key, options, include_query: false)}"
115+
"APIAuth#{hmac_string} #{access_id}:#{hmac_signature(headers, secret_key, options)}"
129116
end
130117

131118
def parse_auth_header(auth_header)

lib/api_auth/headers.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def timestamp
7070
@request.timestamp
7171
end
7272

73-
def canonical_string(override_method = nil, headers_to_sign = [], include_query: false)
73+
def canonical_string(override_method = nil, headers_to_sign = [])
7474
request_method = override_method || @request.http_method
7575

7676
raise ArgumentError, 'unable to determine the http method from the request, please supply an override' if request_method.nil?
@@ -80,7 +80,7 @@ def canonical_string(override_method = nil, headers_to_sign = [], include_query:
8080
canonical_array = [request_method.upcase,
8181
@request.content_type,
8282
@request.content_hash,
83-
parse_uri(@request.original_uri || @request.request_uri, include_query: include_query),
83+
parse_uri(@request.original_uri || @request.request_uri),
8484
@request.timestamp]
8585

8686
if headers_to_sign.is_a?(Array) && headers_to_sign.any?
@@ -125,8 +125,8 @@ def sign_header(header)
125125

126126
private
127127

128-
def parse_uri(uri, include_query: false)
129-
canonical_request_uri(uri, nil, include_query: include_query)
128+
def parse_uri(uri)
129+
canonical_request_uri(uri)
130130
end
131131
end
132132
end

lib/api_auth/helpers.rb

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,13 @@ def value_present?(value)
3636
!value_blank?(value)
3737
end
3838

39-
def canonical_request_uri(base_url, additional_query = nil, include_query: false)
39+
def canonical_request_uri(base_url, additional_query = nil)
4040
base = base_url.to_s
4141
return '/' if base.empty?
4242

4343
uri = URI.parse(base)
44-
if include_query
45-
merged_query = merge_query_strings(uri.query, normalize_query_component(additional_query))
46-
uri.query = merged_query if value_present?(merged_query)
47-
else
48-
uri.query = nil
49-
end
44+
merged_query = merge_query_strings(uri.query, normalize_query_component(additional_query))
45+
uri.query = merged_query if value_present?(merged_query)
5046

5147
result = uri.respond_to?(:request_uri) ? uri.request_uri : uri.to_s
5248
value_present?(result) ? result : '/'

lib/api_auth/request_drivers/typhoeus_request.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def original_uri
5555
end
5656

5757
def request_uri
58-
canonical_request_uri(@request.base_url, params_query, include_query: true)
58+
canonical_request_uri(@request.base_url, params_query)
5959
end
6060

6161
def set_date

spec/api_auth_spec.rb

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -176,44 +176,6 @@ def hmac(secret_key, request, canonical_string = nil, digest = 'sha1')
176176
expect(ApiAuth.authentic?(signed_request, '123', headers_to_sign: %w[HTTP_X_FORWARDED_FOR])).to eq true
177177
end
178178
end
179-
180-
context 'legacy query parameter compatibility' do
181-
let(:legacy_request) do
182-
Net::HTTP::Get.new('/resource.xml?foo=bar&bar=foo',
183-
'content-type' => 'text/plain',
184-
'date' => Time.now.utc.httpdate)
185-
end
186-
let(:access_id) { 'legacy' }
187-
let(:secret_key) { 'secret' }
188-
let(:headers) { ApiAuth::Headers.new(legacy_request) }
189-
190-
def legacy_signature(headers, secret)
191-
canonical = headers.canonical_string(nil, [], include_query: true)
192-
digest = OpenSSL::Digest.new('sha1')
193-
ApiAuth.b64_encode(OpenSSL::HMAC.digest(digest, secret, canonical))
194-
end
195-
196-
before do
197-
sig = legacy_signature(headers, secret_key)
198-
legacy_request['Authorization'] = "APIAuth #{access_id}:#{sig}"
199-
end
200-
201-
around do |example|
202-
original = ApiAuth.legacy_query_params_compatibility?
203-
example.run
204-
ApiAuth.legacy_query_params_compatibility = original
205-
end
206-
207-
it 'rejects legacy signatures by default' do
208-
ApiAuth.legacy_query_params_compatibility = false
209-
expect(ApiAuth.authentic?(legacy_request, secret_key)).to eq false
210-
end
211-
212-
it 'accepts legacy signatures when compatibility is enabled' do
213-
ApiAuth.legacy_query_params_compatibility = true
214-
expect(ApiAuth.authentic?(legacy_request, secret_key)).to eq true
215-
end
216-
end
217179
end
218180

219181
describe '.access_id' do

spec/headers_spec.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
context 'uri has a string matching https:// in it' do
3535
let(:uri) { 'https://google.com/?redirect_to=https://www.example.com'.freeze }
3636

37-
it 'return / as canonical string path' do
38-
expect(subject.canonical_string).to eq('GET,,,/,')
37+
it 'return /?redirect_to=https://www.example.com as canonical string path' do
38+
expect(subject.canonical_string).to eq('GET,,,/?redirect_to=https://www.example.com,')
3939
end
4040

4141
it 'does not change request url (by removing host)' do
@@ -121,7 +121,7 @@
121121

122122
context 'the driver uses the original_uri' do
123123
it 'constructs the canonical_string with the original_uri' do
124-
expect(headers.canonical_string).to eq 'GET,text/html,12345,/api/resource.xml,Mon, 23 Jan 1984 03:29:56 GMT'
124+
expect(headers.canonical_string).to eq 'GET,text/html,12345,/api/resource.xml?foo=bar&bar=foo,Mon, 23 Jan 1984 03:29:56 GMT'
125125
end
126126
end
127127
end
@@ -147,7 +147,7 @@
147147
context 'the driver uses the original_uri' do
148148
it 'constructs the canonical_string with the original_uri' do
149149
expect(headers.canonical_string(nil, %w[X-FORWARDED-FOR]))
150-
.to eq 'GET,text/html,12345,/resource.xml,Mon, 23 Jan 1984 03:29:56 GMT,192.168.1.1'
150+
.to eq 'GET,text/html,12345,/resource.xml?bar=foo&foo=bar,Mon, 23 Jan 1984 03:29:56 GMT,192.168.1.1'
151151
end
152152
end
153153
end

0 commit comments

Comments
 (0)