mauth-client 5.1.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
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