mauth-client 5.1.0 → 6.0.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: 73a877135a7440cd3137c471873a1ac760304a31cac524189045448c122dc2a8
4
- data.tar.gz: e817da8c2d7de3e5d2629de33ded9f8e5985cbc6923dca057de49738460d6ea1
3
+ metadata.gz: 0ac6251a66453ac4fe6f1f449d407173851a6c34e3dd17bf3b80d816e619e045
4
+ data.tar.gz: bf6f603408e51a6af3965e458f736ee3ed07763a7f0a662f1af0bd67a1cbeab3
5
5
  SHA512:
6
- metadata.gz: ca1e092bbfbc376f1dac96da7198fdc94b234ccd9086a373de69d4ee7e638971e964ab5a549330beeacbf811b2b3990fbef6d7672b498a42d07c6d5518f7e6ad
7
- data.tar.gz: 230c42bd030c4bac0dab46c365acda69d8011ab06060156a7244c9f1319ca9248630f2ba29c5c35732d456be8d0734260580c8c1cda0ee40bd8f0182970dadec
6
+ metadata.gz: e4faea9d5bcf10c64b3c3bc10dded82d14b68bce39312b87140e38ba5410ba9d67b993f94e2e96036d7d88550837a6088d43deb75d7e4fed8164b51ed81b296c
7
+ data.tar.gz: a7a71824118eb6b4ca88a7f8a7afdb85719613997754392147dfa348eae7c04faf4ba7458eb28375d8b596c6b609ecbe6e8c42d5caed4931b9427c843bbf9448
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --tag ~protocol_suite
@@ -1,3 +1,11 @@
1
+ ## v.6.0.0
2
+ - Added parsing code to test with mauth-protocol-test-suite.
3
+ - Added unescape step in query_string encoding in order to remove 'double encoding'.
4
+ - Added normalization of paths.
5
+ - Added flag to sign only with V1.
6
+ - Changed V2 to V1 fallback to be configurable.
7
+ - Fixed bug in sorting query parameters.
8
+
1
9
  ## v5.1.0
2
10
  - Fall back to V1 when V2 authentication fails.
3
11
 
@@ -19,6 +19,14 @@ Next, run the tests:
19
19
  bundle exec rspec
20
20
  ```
21
21
 
22
+ # Running mauth-protocol-test-suite
23
+
24
+ To run the mauth-protocol-test-suite clone the latest test suite onto your machine and place it in the same parent directory as this repo (or supply the ENV var `TEST_SUITE_RELATIVE_PATH` with the path to the test suite relative to this repo). Then run:
25
+
26
+ ```
27
+ bundle exec rspec --tag protocol_suite
28
+ ```
29
+
22
30
  ## Running Benchmark
23
31
 
24
32
  If you make changes which could affect performance, please run the benchmark before and after the change as a sanity check.
@@ -31,6 +31,7 @@ common: &common
31
31
  -----END RSA PRIVATE KEY-----
32
32
  v2_only_authenticate: false
33
33
  v2_only_sign_requests: false
34
+ disable_fallback_to_v1_on_v2_failure: true
34
35
 
35
36
  production:
36
37
  <<: *common
@@ -50,6 +51,8 @@ common: &common
50
51
  private_key_file: config/my_mauth_private.key
51
52
  v2_only_authenticate: false
52
53
  v2_only_sign_requests: false
54
+ disable_fallback_to_v1_on_v2_failure: true
55
+ v1_only_sign_requests: false
53
56
 
54
57
  production:
55
58
  <<: *common
@@ -66,8 +69,10 @@ test:
66
69
  - `app_uuid` - Required in the same circumstances where a `private_key` is required.
67
70
  - `mauth_baseurl` - Required for authentication but not for signing. Needed for local authentication to retrieve public keys and for remote authentication. Usually this is `https://mauth.imedidata.com` for production.
68
71
  - `mauth_api_version` - Required for authentication but not for signing. only `v1` exists as of this writing.
69
- - `v2_only_authenticate` - If true, all outgoing requests will be signed with only the V2 protocol.
70
- - `v2_only_sign_requests` - If true, any incoming request or incoming response that does not use the V2 protocol will be rejected.
72
+ - `v2_only_sign_requests` - If true, all outgoing requests will be signed with only the V2 protocol. Defaults to false.
73
+ - `v2_only_authenticate` - If true, any incoming request or incoming response that does not use the V2 protocol will be rejected. Defaults to false.
74
+ - `disable_fallback_to_v1_on_v2_failure` - If true, any incoming V2 requests that fail authentication will not fall back to V1 authentication. Defaults to false.
75
+ - `v1_only_sign_requests` - If true, all outgoing requests will be signed with only the V1 protocol. Defaults to true. Note, cannot be `true` if `v2_only_sign_requests` is also `true`.
71
76
 
72
77
  ## Usage in your application
73
78
 
@@ -153,6 +153,12 @@ module MAuth
153
153
  @config['ssl_certs_path'] = given_config['ssl_certs_path'] if given_config['ssl_certs_path']
154
154
  @config['v2_only_authenticate'] = given_config['v2_only_authenticate'].to_s.downcase == 'true'
155
155
  @config['v2_only_sign_requests'] = given_config['v2_only_sign_requests'].to_s.downcase == 'true'
156
+ @config['disable_fallback_to_v1_on_v2_failure'] = given_config['disable_fallback_to_v1_on_v2_failure'].to_s.downcase == 'true'
157
+ @config['v1_only_sign_requests'] = given_config['v1_only_sign_requests'].to_s.downcase == 'true'
158
+
159
+ if @config['v2_only_sign_requests'] && @config['v1_only_sign_requests']
160
+ raise MAuth::Client::ConfigurationError, "v2_only_sign_requests and v1_only_sign_requests may not both be true"
161
+ end
156
162
 
157
163
  # if 'authenticator' was given, don't override that - including if it was given as nil / false
158
164
  if given_config.key?('authenticator')
@@ -205,6 +211,14 @@ module MAuth
205
211
  @config['v2_only_authenticate']
206
212
  end
207
213
 
214
+ def disable_fallback_to_v1_on_v2_failure?
215
+ @config['disable_fallback_to_v1_on_v2_failure']
216
+ end
217
+
218
+ def v1_only_sign_requests?
219
+ @config['v1_only_sign_requests']
220
+ end
221
+
208
222
  def assert_private_key(err)
209
223
  raise err unless private_key
210
224
  end
@@ -19,13 +19,14 @@ module MAuth
19
19
 
20
20
  # raises InauthenticError unless the given object is authentic. Will only
21
21
  # authenticate with v2 if the environment variable V2_ONLY_AUTHENTICATE
22
- # is set. Otherwise will fallback to v1 when v2 authentication fails
22
+ # is set. Otherwise will fall back to v1 when v2 authentication fails
23
23
  def authenticate!(object)
24
24
  if object.protocol_version == 2
25
25
  begin
26
26
  authenticate_v2!(object)
27
27
  rescue InauthenticError => e
28
28
  raise e if v2_only_authenticate?
29
+ raise e if disable_fallback_to_v1_on_v2_failure?
29
30
 
30
31
  object.fall_back_to_mws_signature_info
31
32
  raise e unless object.signature
@@ -30,6 +30,8 @@ module MAuth
30
30
  def signed_headers(object, attributes = {})
31
31
  if v2_only_sign_requests?
32
32
  signed_headers_v2(object, attributes)
33
+ elsif v1_only_sign_requests?
34
+ signed_headers_v1(object, attributes)
33
35
  else # by default sign with both the v1 and v2 protocol
34
36
  signed_headers_v1(object, attributes).merge(signed_headers_v2(object, attributes))
35
37
  end
@@ -7,6 +7,8 @@ common: &common
7
7
  private_key_file: config/mauth_key
8
8
  v2_only_authenticate: <%= configured.v2_only_authenticate || 'false' %>
9
9
  v2_only_sign_requests: <%= configured.v2_only_sign_requests || 'false' %>
10
+ disable_fallback_to_v1_on_v2_failure: <%= configured.disable_fallback_to_v1_on_v2_failure || 'false' %>
11
+ v1_only_sign_requests: <%= configured.v1_only_sign_requests || 'true' %>
10
12
 
11
13
  production:
12
14
  <<: *common
@@ -1,4 +1,5 @@
1
1
  require 'digest'
2
+ require 'addressable'
2
3
 
3
4
  module MAuth
4
5
  # module which composes a string to sign.
@@ -61,7 +62,8 @@ module MAuth
61
62
  # string_to_sign_v2 three times in client#signature_valid_v2!
62
63
  # note that if :body is nil we hash an empty string ('')
63
64
  attrs_with_overrides[:body_digest] ||= Digest::SHA512.hexdigest(attrs_with_overrides[:body] || '')
64
- attrs_with_overrides[:encoded_query_params] = encode_query_string(attrs_with_overrides[:query_string] || '')
65
+ attrs_with_overrides[:encoded_query_params] = unescape_encode_query_string(attrs_with_overrides[:query_string] || '')
66
+ attrs_with_overrides[:request_url] = normalize_path(attrs_with_overrides[:request_url])
65
67
 
66
68
  missing_attributes = self.class::SIGNATURE_COMPONENTS_V2.reject do |key|
67
69
  attrs_with_overrides.dig(key)
@@ -78,12 +80,26 @@ module MAuth
78
80
  end.join("\n")
79
81
  end
80
82
 
83
+ # Addressable::URI.parse(path).normalize.to_s.squeeze('/')
84
+ def normalize_path(path)
85
+ return if path.nil?
86
+
87
+ # Addressable::URI.normalize_path normalizes `.` and `..` in path
88
+ # i.e. /./example => /example ; /example/.. => /
89
+ # String#squeeze removes duplicated slahes i.e. /// => /
90
+ # String#gsub normalizes percent encoding to uppercase i.e. %cf%80 => %CF%80
91
+ Addressable::URI.normalize_path(path).squeeze('/').
92
+ gsub(/%[a-f0-9]{2}/, &:upcase)
93
+ end
94
+
81
95
  # sorts query string parameters by codepoint, uri encodes keys and values,
82
96
  # and rejoins parameters into a query string
83
- def encode_query_string(q_string)
84
- q_string.split('&').sort.map do |part|
85
- k, e, v = part.partition('=')
86
- uri_escape(k) + e + uri_escape(v)
97
+ def unescape_encode_query_string(q_string)
98
+ fir = q_string.split('&').map do |part|
99
+ k, _eq, v = part.partition('=')
100
+ [CGI.unescape(k), CGI.unescape(v)]
101
+ end.sort.map do |k, v|
102
+ "#{uri_escape(k)}=#{uri_escape(v)}"
87
103
  end.join('&')
88
104
  end
89
105
 
@@ -116,7 +132,7 @@ module MAuth
116
132
  # - #x_mws_time
117
133
  module Signed
118
134
  # mauth_client will authenticate with the highest protocol version present and if authentication fails,
119
- # will fallback to lower protocol versions (if provided).
135
+ # will fall back to lower protocol versions (if provided).
120
136
  # returns a hash with keys :token, :app_uuid, and :signature parsed from the MCC-Authentication header
121
137
  # if it is present and if not then the X-MWS-Authentication header if it is present.
122
138
  # Note MWSV2 protocol no longer allows more than one space between the token and app uuid.
@@ -1,3 +1,3 @@
1
1
  module MAuth
2
- VERSION = '5.1.0'.freeze
2
+ VERSION = '6.0.0'.freeze
3
3
  end
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.add_dependency 'coderay', '~> 1.0'
25
25
  spec.add_dependency 'rack'
26
26
  spec.add_dependency 'dice_bag', '>= 0.9', '< 2.0'
27
+ spec.add_dependency 'addressable', '~> 2.0'
27
28
 
28
29
  spec.add_development_dependency 'bundler', '>= 1.17'
29
30
  spec.add_development_dependency 'byebug'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mauth-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.0
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Szenher
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2020-01-15 00:00:00.000000000 Z
14
+ date: 2020-05-07 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: faraday
@@ -103,6 +103,20 @@ dependencies:
103
103
  - - "<"
104
104
  - !ruby/object:Gem::Version
105
105
  version: '2.0'
106
+ - !ruby/object:Gem::Dependency
107
+ name: addressable
108
+ requirement: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - "~>"
111
+ - !ruby/object:Gem::Version
112
+ version: '2.0'
113
+ type: :runtime
114
+ prerelease: false
115
+ version_requirements: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '2.0'
106
120
  - !ruby/object:Gem::Dependency
107
121
  name: bundler
108
122
  requirement: !ruby/object:Gem::Requirement
@@ -228,6 +242,7 @@ extra_rdoc_files: []
228
242
  files:
229
243
  - ".fossa.yml"
230
244
  - ".gitignore"
245
+ - ".rspec"
231
246
  - ".travis.yml"
232
247
  - ".yardopts"
233
248
  - CHANGELOG.md