mauth-client 6.2.0 → 6.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/exe/mauth-proxy CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  $LOAD_PATH.unshift File.expand_path('../lib', File.dirname(__FILE__))
4
5
 
5
- require 'rubygems'
6
6
  require 'mauth/proxy'
7
7
  require 'rack'
8
8
 
9
9
  headers = []
10
10
  headers_index = ARGV.find_index('--header')
11
- while(headers_index) do
11
+ while headers_index
12
12
  headers << ARGV[headers_index + 1]
13
13
  ARGV.delete_at(headers_index + 1)
14
14
  ARGV.delete_at(headers_index)
@@ -16,25 +16,25 @@ while(headers_index) do
16
16
  end
17
17
 
18
18
  authenticate_responses = !ARGV.delete('--no-authenticate')
19
- browser_proxy = !(ARGV.delete('--browser_proxy').nil?)
19
+ browser_proxy = !ARGV.delete('--browser_proxy').nil?
20
20
 
21
21
  target_uri = browser_proxy ? ARGV : ARGV.pop
22
22
 
23
23
  if !target_uri || target_uri.empty?
24
- abort("Usage: mauth-proxy [rack options] --browser_proxy [--no-authenticate] <target URI> <target URI> ...\n" +
25
- "or: mauth-proxy [rack options] <target URI>")
24
+ abort("Usage: mauth-proxy [rack options] --browser_proxy [--no-authenticate] <target URI> <target URI> ...\n" \
25
+ 'or: mauth-proxy [rack options] <target URI>')
26
26
  end
27
27
 
28
28
  rack_server_options = Rack::Server::Options.new.parse!(ARGV)
29
29
 
30
- # for security, this rack server will only accept local connections, so override Host
30
+ # for security, this rack server will only accept local connections, so override Host
31
31
  # to 127.0.0.1 (from the default of 0.0.0.0)
32
32
  #
33
- # this means that the '-o' / '--host' option to Rack::Server::Options is ignored.
34
- rack_server_options[:Host] = "127.0.0.1"
33
+ # this means that the '-o' / '--host' option to Rack::Server::Options is ignored.
34
+ rack_server_options[:Host] = '127.0.0.1'
35
35
 
36
- rack_server_options[:app] = MAuth::Proxy.new(target_uri, :authenticate_responses => authenticate_responses,
37
- :browser_proxy => browser_proxy, :headers => headers)
36
+ rack_server_options[:app] = MAuth::Proxy.new(target_uri, authenticate_responses: authenticate_responses,
37
+ browser_proxy: browser_proxy, headers: headers)
38
38
 
39
39
  mauth_proxy_server = Rack::Server.new(rack_server_options)
40
40
  mauth_proxy_server.start
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "faraday", "~> 2.0"
6
+
7
+ gemspec path: "../"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MAuth
2
4
  autoload :Client, 'mauth/client'
3
5
  autoload :Middleware, 'mauth/middleware'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # methods common to RemoteRequestAuthenticator and LocalAuthenticator
2
4
 
3
5
  module MAuth
@@ -21,7 +23,8 @@ module MAuth
21
23
  # authenticate with v2 if the environment variable V2_ONLY_AUTHENTICATE
22
24
  # is set. Otherwise will fall back to v1 when v2 authentication fails
23
25
  def authenticate!(object)
24
- if object.protocol_version == 2
26
+ case object.protocol_version
27
+ when 2
25
28
  begin
26
29
  authenticate_v2!(object)
27
30
  rescue InauthenticError => e
@@ -33,9 +36,9 @@ module MAuth
33
36
 
34
37
  log_authentication_request(object)
35
38
  authenticate_v1!(object)
36
- logger.warn("Completed successful authentication attempt after fallback to v1")
39
+ logger.warn('Completed successful authentication attempt after fallback to v1')
37
40
  end
38
- elsif object.protocol_version == 1
41
+ when 1
39
42
  if v2_only_authenticate?
40
43
  # If v2 is required but not present and v1 is present we raise MissingV2Error
41
44
  msg = 'This service requires mAuth v2 mcc-authentication header but only v1 x-mws-authentication is present'
@@ -54,13 +57,13 @@ module MAuth
54
57
 
55
58
  private
56
59
 
57
- # Note: This log is likely consumed downstream and the contents SHOULD NOT
60
+ # NOTE: This log is likely consumed downstream and the contents SHOULD NOT
58
61
  # be changed without a thorough review of downstream consumers.
59
62
  def log_authentication_request(object)
60
63
  object_app_uuid = object.signature_app_uuid || '[none provided]'
61
64
  object_token = object.signature_token || '[none provided]'
62
65
  logger.info(
63
- "Mauth-client attempting to authenticate request from app with mauth" \
66
+ 'Mauth-client attempting to authenticate request from app with mauth' \
64
67
  " app uuid #{object_app_uuid} to app with mauth app uuid #{client_app_uuid}" \
65
68
  " using version #{object_token}."
66
69
  )
@@ -71,7 +74,7 @@ module MAuth
71
74
  end
72
75
 
73
76
  def time_within_valid_range!(object, time_signed, now = Time.now)
74
- return if (-ALLOWED_DRIFT_SECONDS..ALLOWED_DRIFT_SECONDS).cover?(now.to_i - time_signed)
77
+ return if (-ALLOWED_DRIFT_SECONDS..ALLOWED_DRIFT_SECONDS).cover?(now.to_i - time_signed)
75
78
 
76
79
  msg = "Time verification failed. #{time_signed} not within #{ALLOWED_DRIFT_SECONDS} of #{now}"
77
80
  log_inauthentic(object, msg)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mauth/client/security_token_cacher'
2
4
  require 'mauth/client/signer'
3
5
  require 'openssl'
@@ -25,11 +27,13 @@ module MAuth
25
27
 
26
28
  # do a simple percent reencoding variant of the path
27
29
  object.attributes_for_signing[:request_url] = CGI.escape(original_request_uri.to_s)
28
- expected_for_percent_reencoding = object.string_to_sign_v1(time: object.x_mws_time, app_uuid: object.signature_app_uuid)
30
+ expected_for_percent_reencoding = object.string_to_sign_v1(time: object.x_mws_time,
31
+ app_uuid: object.signature_app_uuid)
29
32
 
30
33
  # do a moderately complex Euresource-style reencoding of the path
31
34
  object.attributes_for_signing[:request_url] = euresource_escape(original_request_uri.to_s)
32
- expected_euresource_style_reencoding = object.string_to_sign_v1(time: object.x_mws_time, app_uuid: object.signature_app_uuid)
35
+ expected_euresource_style_reencoding = object.string_to_sign_v1(time: object.x_mws_time,
36
+ app_uuid: object.signature_app_uuid)
33
37
 
34
38
  # reset the object original request_uri, just in case we need it again
35
39
  object.attributes_for_signing[:request_url] = original_request_uri
@@ -44,8 +48,8 @@ module MAuth
44
48
  end
45
49
 
46
50
  unless verify_signature_v1!(actual, expected_no_reencoding) ||
47
- verify_signature_v1!(actual, expected_euresource_style_reencoding) ||
48
- verify_signature_v1!(actual, expected_for_percent_reencoding)
51
+ verify_signature_v1!(actual, expected_euresource_style_reencoding) ||
52
+ verify_signature_v1!(actual, expected_for_percent_reencoding)
49
53
  msg = "Signature verification failed for #{object.class}"
50
54
  log_inauthentic(object, msg)
51
55
  raise InauthenticError, msg
@@ -53,7 +57,7 @@ module MAuth
53
57
  end
54
58
 
55
59
  def verify_signature_v1!(actual, expected_str_to_sign)
56
- actual == Digest::SHA512.hexdigest(expected_str_to_sign)
60
+ actual == OpenSSL::Digest::SHA512.hexdigest(expected_str_to_sign)
57
61
  end
58
62
 
59
63
  def signature_valid_v2!(object)
@@ -93,8 +97,8 @@ module MAuth
93
97
  actual = Base64.decode64(object.signature)
94
98
 
95
99
  unless verify_signature_v2!(object, actual, pubkey, expected_no_reencoding) ||
96
- verify_signature_v2!(object, actual, pubkey, expected_euresource_style_reencoding) ||
97
- verify_signature_v2!(object, actual, pubkey, expected_for_percent_reencoding)
100
+ verify_signature_v2!(object, actual, pubkey, expected_euresource_style_reencoding) ||
101
+ verify_signature_v2!(object, actual, pubkey, expected_for_percent_reencoding)
98
102
  msg = "Signature inauthentic for #{object.class}"
99
103
  log_inauthentic(object, msg)
100
104
  raise InauthenticError, msg
@@ -113,7 +117,7 @@ module MAuth
113
117
  raise InauthenticError, msg
114
118
  end
115
119
 
116
- # Note: RFC 3986 (https://www.ietf.org/rfc/rfc3986.txt) reserves the forward slash "/"
120
+ # NOTE: RFC 3986 (https://www.ietf.org/rfc/rfc3986.txt) reserves the forward slash "/"
117
121
  # and number sign "#" as component delimiters. Since these are valid URI components,
118
122
  # they are decoded back into characters here to avoid signature invalidation
119
123
  def euresource_escape(str)
@@ -139,7 +143,6 @@ module MAuth
139
143
  def security_token_cacher
140
144
  @security_token_cacher ||= SecurityTokenCacher.new(self)
141
145
  end
142
-
143
146
  end
144
147
  end
145
148
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # methods for remotely authenticating a request by sending it to the mauth service
2
4
 
3
5
  module MAuth
@@ -8,7 +10,11 @@ module MAuth
8
10
  # takes an incoming request object (no support for responses currently), and errors if the
9
11
  # object is not authentic according to its signature
10
12
  def signature_valid_v1!(object)
11
- raise ArgumentError, "Remote Authenticator can only authenticate requests; received #{object.inspect}" unless object.is_a?(MAuth::Request)
13
+ unless object.is_a?(MAuth::Request)
14
+ raise ArgumentError,
15
+ "Remote Authenticator can only authenticate requests; received #{object.inspect}"
16
+ end
17
+
12
18
  authentication_ticket = {
13
19
  'verb' => object.attributes_for_signing[:verb],
14
20
  'app_uuid' => object.signature_app_uuid,
@@ -41,15 +47,17 @@ module MAuth
41
47
 
42
48
  def make_mauth_request(authentication_ticket)
43
49
  begin
44
- response = mauth_connection.post("/mauth/#{mauth_api_version}/authentication_tickets.json", 'authentication_ticket' => authentication_ticket)
50
+ request_body = JSON.generate(authentication_ticket: authentication_ticket)
51
+ response = mauth_connection.post("/mauth/#{mauth_api_version}/authentication_tickets.json", request_body)
45
52
  rescue ::Faraday::ConnectionFailed, ::Faraday::TimeoutError => e
46
53
  msg = "mAuth service did not respond; received #{e.class}: #{e.message}"
47
54
  logger.error("Unable to authenticate with MAuth. Exception #{msg}")
48
55
  raise UnableToAuthenticateError, msg
49
56
  end
50
- if (200..299).cover?(response.status)
57
+ case response.status
58
+ when 200..299
51
59
  nil
52
- elsif response.status == 412 || response.status == 404
60
+ when 412, 404
53
61
  # the mAuth service responds with 412 when the given request is not authentically signed.
54
62
  # older versions of the mAuth service respond with 404 when the given app_uuid
55
63
  # does not exist, which is also considered to not be authentically signed. newer
@@ -62,12 +70,14 @@ module MAuth
62
70
  end
63
71
 
64
72
  def mauth_connection
65
- require 'faraday'
66
- require 'faraday_middleware'
67
- @mauth_connection ||= ::Faraday.new(mauth_baseurl, faraday_options) do |builder|
68
- builder.use MAuth::Faraday::MAuthClientUserAgent
69
- builder.use FaradayMiddleware::EncodeJson
70
- builder.adapter ::Faraday.default_adapter
73
+ @mauth_connection ||= begin
74
+ require 'faraday'
75
+
76
+ ::Faraday.new(mauth_baseurl,
77
+ faraday_options.merge(headers: { 'Content-Type' => 'application/json' })) do |builder|
78
+ builder.use MAuth::Faraday::MAuthClientUserAgent
79
+ builder.adapter ::Faraday.default_adapter
80
+ end
71
81
  end
72
82
  end
73
83
  end
@@ -1,44 +1,40 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday-http-cache'
2
- require 'oj'
4
+ require 'mauth/faraday'
3
5
 
4
6
  module MAuth
5
7
  class Client
6
8
  module LocalAuthenticator
7
9
  class SecurityTokenCacher
8
-
9
10
  def initialize(mauth_client)
10
11
  @mauth_client = mauth_client
11
12
  # TODO: should this be UnableToSignError?
12
- @mauth_client.assert_private_key(UnableToAuthenticateError.new("Cannot fetch public keys from mAuth service without a private key!"))
13
- @cache = {}
14
- require 'thread'
15
- @cache_write_lock = Mutex.new
13
+ @mauth_client.assert_private_key(
14
+ UnableToAuthenticateError.new('Cannot fetch public keys from mAuth service without a private key!')
15
+ )
16
16
  end
17
17
 
18
18
  def get(app_uuid)
19
- if !@cache[app_uuid]
20
- # url-encode the app_uuid to prevent trickery like escaping upward with ../../ in a malicious
21
- # app_uuid - probably not exploitable, but this is the right way to do it anyway.
22
- url_encoded_app_uuid = CGI.escape(app_uuid)
23
- begin
24
- response = signed_mauth_connection.get("/mauth/#{@mauth_client.mauth_api_version}/security_tokens/#{url_encoded_app_uuid}.json")
25
- rescue ::Faraday::ConnectionFailed, ::Faraday::TimeoutError => e
26
- msg = "mAuth service did not respond; received #{e.class}: #{e.message}"
27
- @mauth_client.logger.error("Unable to authenticate with MAuth. Exception #{msg}")
28
- raise UnableToAuthenticateError, msg
29
- end
30
- if response.status == 200
31
- @cache_write_lock.synchronize do
32
- @cache[app_uuid] = security_token_from(response.body)
33
- end
34
- elsif response.status == 404
35
- # signing with a key mAuth doesn't know about is considered inauthentic
36
- raise InauthenticError, "mAuth service responded with 404 looking up public key for #{app_uuid}"
37
- else
38
- @mauth_client.send(:mauth_service_response_error, response)
39
- end
19
+ # url-encode the app_uuid to prevent trickery like escaping upward with ../../ in a malicious
20
+ # app_uuid - probably not exploitable, but this is the right way to do it anyway.
21
+ url_encoded_app_uuid = CGI.escape(app_uuid)
22
+ path = "/mauth/#{@mauth_client.mauth_api_version}/security_tokens/#{url_encoded_app_uuid}.json"
23
+ response = signed_mauth_connection.get(path)
24
+
25
+ case response.status
26
+ when 200
27
+ security_token_from(response.body)
28
+ when 404
29
+ # signing with a key mAuth doesn't know about is considered inauthentic
30
+ raise InauthenticError, "mAuth service responded with 404 looking up public key for #{app_uuid}"
31
+ else
32
+ @mauth_client.send(:mauth_service_response_error, response)
40
33
  end
41
- @cache[app_uuid]
34
+ rescue ::Faraday::ConnectionFailed, ::Faraday::TimeoutError => e
35
+ msg = "mAuth service did not respond; received #{e.class}: #{e.message}"
36
+ @mauth_client.logger.error("Unable to authenticate with MAuth. Exception #{msg}")
37
+ raise UnableToAuthenticateError, msg
42
38
  end
43
39
 
44
40
  private
@@ -46,20 +42,23 @@ module MAuth
46
42
  def security_token_from(response_body)
47
43
  JSON.parse response_body
48
44
  rescue JSON::ParserError => e
49
- msg = "mAuth service responded with unparseable json: #{response_body}\n#{e.class}: #{e.message}"
45
+ msg = "mAuth service responded with unparseable json: #{response_body}\n#{e.class}: #{e.message}"
50
46
  @mauth_client.logger.error("Unable to authenticate with MAuth. Exception #{msg}")
51
47
  raise UnableToAuthenticateError, msg
52
48
  end
53
49
 
54
50
  def signed_mauth_connection
55
- require 'faraday'
56
- require 'mauth/faraday'
57
- @mauth_client.faraday_options[:ssl] = { ca_path: @mauth_client.ssl_certs_path } if @mauth_client.ssl_certs_path
58
- @signed_mauth_connection ||= ::Faraday.new(@mauth_client.mauth_baseurl, @mauth_client.faraday_options) do |builder|
59
- builder.use MAuth::Faraday::MAuthClientUserAgent
60
- builder.use MAuth::Faraday::RequestSigner, 'mauth_client' => @mauth_client
61
- builder.use :http_cache, serializer: Oj, logger: MAuth::Client.new.logger, shared_cache: false
62
- builder.adapter ::Faraday.default_adapter
51
+ @signed_mauth_connection ||= begin
52
+ if @mauth_client.ssl_certs_path
53
+ @mauth_client.faraday_options[:ssl] = { ca_path: @mauth_client.ssl_certs_path }
54
+ end
55
+
56
+ ::Faraday.new(@mauth_client.mauth_baseurl, @mauth_client.faraday_options) do |builder|
57
+ builder.use MAuth::Faraday::MAuthClientUserAgent
58
+ builder.use MAuth::Faraday::RequestSigner, 'mauth_client' => @mauth_client
59
+ builder.use :http_cache, logger: MAuth::Client.new.logger, shared_cache: false
60
+ builder.adapter ::Faraday.default_adapter
61
+ end
63
62
  end
64
63
  end
65
64
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'openssl'
2
4
  require 'mauth/errors'
3
5
 
@@ -5,7 +7,7 @@ require 'mauth/errors'
5
7
 
6
8
  module MAuth
7
9
  class Client
8
- SIGNING_DIGEST = OpenSSL::Digest::SHA512.new
10
+ SIGNING_DIGEST = OpenSSL::Digest.new('SHA512')
9
11
 
10
12
  module Signer
11
13
  UNABLE_TO_SIGN_ERR = UnableToSignError.new('mAuth client cannot sign without a private key!')
@@ -40,14 +42,14 @@ module MAuth
40
42
  def signed_headers_v1(object, attributes = {})
41
43
  attributes = { time: Time.now.to_i.to_s, app_uuid: client_app_uuid }.merge(attributes)
42
44
  string_to_sign = object.string_to_sign_v1(attributes)
43
- signature = self.signature_v1(string_to_sign)
45
+ signature = signature_v1(string_to_sign)
44
46
  { 'X-MWS-Authentication' => "#{MWS_TOKEN} #{client_app_uuid}:#{signature}", 'X-MWS-Time' => attributes[:time] }
45
47
  end
46
48
 
47
49
  def signed_headers_v2(object, attributes = {})
48
50
  attributes = { time: Time.now.to_i.to_s, app_uuid: client_app_uuid }.merge(attributes)
49
51
  string_to_sign = object.string_to_sign_v2(attributes)
50
- signature = self.signature_v2(string_to_sign)
52
+ signature = signature_v2(string_to_sign)
51
53
  {
52
54
  'MCC-Authentication' => "#{MWSV2_TOKEN} #{client_app_uuid}:#{signature}#{AUTH_HEADER_DELIMITER}",
53
55
  'MCC-Time' => attributes[:time]
@@ -56,7 +58,7 @@ module MAuth
56
58
 
57
59
  def signature_v1(string_to_sign)
58
60
  assert_private_key(UNABLE_TO_SIGN_ERR)
59
- hashed_string_to_sign = Digest::SHA512.hexdigest(string_to_sign)
61
+ hashed_string_to_sign = OpenSSL::Digest::SHA512.hexdigest(string_to_sign)
60
62
  Base64.encode64(private_key.private_encrypt(hashed_string_to_sign)).delete("\n")
61
63
  end
62
64
 
data/lib/mauth/client.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
  require 'openssl'
3
5
  require 'base64'
@@ -24,9 +26,9 @@ module MAuth
24
26
  # that the object responds to the methods of MAuth::Signable and/or MAuth::Signed (as
25
27
  # appropriate)
26
28
  class Client
27
- MWS_TOKEN = 'MWS'.freeze
28
- MWSV2_TOKEN = 'MWSV2'.freeze
29
- AUTH_HEADER_DELIMITER = ';'.freeze
29
+ MWS_TOKEN = 'MWS'
30
+ MWSV2_TOKEN = 'MWSV2'
31
+ AUTH_HEADER_DELIMITER = ';'
30
32
 
31
33
  include AuthenticatorBase
32
34
  include Signer
@@ -53,7 +55,7 @@ module MAuth
53
55
  # find the app_root (relative to which we look for yaml files). note that this
54
56
  # is different than MAuth::Client.root, the root of the mauth-client library.
55
57
  app_root = options['root'] || begin
56
- if Object.const_defined?('Rails') && ::Rails.respond_to?(:root) && ::Rails.root
58
+ if Object.const_defined?(:Rails) && ::Rails.respond_to?(:root) && ::Rails.root
57
59
  Rails.root
58
60
  else
59
61
  ENV['RAILS_ROOT'] || ENV['RACK_ROOT'] || ENV['APP_ROOT'] || '.'
@@ -62,7 +64,7 @@ module MAuth
62
64
 
63
65
  # find the environment (with which yaml files are keyed)
64
66
  env = options['environment'] || begin
65
- if Object.const_defined?('Rails') && ::Rails.respond_to?(:environment)
67
+ if Object.const_defined?(:Rails) && ::Rails.respond_to?(:environment)
66
68
  Rails.environment
67
69
  else
68
70
  ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
@@ -82,16 +84,17 @@ module MAuth
82
84
  errmessage = "#{mauth_config_yml} config has no key #{env} - it has keys #{whole_config.keys.inspect}"
83
85
  whole_config[env] || raise(MAuth::Client::ConfigurationError, errmessage)
84
86
  else
85
- raise MAuth::Client::ConfigurationError, "could not find mauth config yaml file. this file may be " \
87
+ raise MAuth::Client::ConfigurationError,
88
+ 'could not find mauth config yaml file. this file may be ' \
86
89
  "placed in #{default_loc}, specified with the mauth_config_yml option, or specified with the " \
87
- "MAUTH_CONFIG_YML environment variable."
90
+ 'MAUTH_CONFIG_YML environment variable.'
88
91
  end
89
92
  end
90
93
 
91
94
  unless mauth_config.key?('logger')
92
95
  # the logger. Rails.logger if it exists, otherwise, no logger
93
96
  mauth_config['logger'] = options['logger'] || begin
94
- if Object.const_defined?('Rails') && ::Rails.respond_to?(:logger)
97
+ if Object.const_defined?(:Rails) && ::Rails.respond_to?(:logger)
95
98
  Rails.logger
96
99
  end
97
100
  end
@@ -122,22 +125,24 @@ module MAuth
122
125
  if given_config['private_key_file'] && !given_config['private_key']
123
126
  given_config['private_key'] = File.read(given_config['private_key_file'])
124
127
  end
125
- @config['private_key'] = case given_config['private_key']
126
- when nil
127
- nil
128
- when String
129
- OpenSSL::PKey::RSA.new(given_config['private_key'])
130
- when OpenSSL::PKey::RSA
131
- given_config['private_key']
132
- else
133
- raise MAuth::Client::ConfigurationError, "unrecognized value given for 'private_key' - this may be a " \
134
- "String, a OpenSSL::PKey::RSA, or omitted; instead got: #{given_config['private_key'].inspect}"
135
- end
128
+ @config['private_key'] =
129
+ case given_config['private_key']
130
+ when nil
131
+ nil
132
+ when String
133
+ OpenSSL::PKey::RSA.new(given_config['private_key'])
134
+ when OpenSSL::PKey::RSA
135
+ given_config['private_key']
136
+ else
137
+ raise MAuth::Client::ConfigurationError,
138
+ "unrecognized value given for 'private_key' - this may be a " \
139
+ "String, a OpenSSL::PKey::RSA, or omitted; instead got: #{given_config['private_key'].inspect}"
140
+ end
136
141
  @config['app_uuid'] = given_config['app_uuid']
137
142
  @config['mauth_baseurl'] = given_config['mauth_baseurl']
138
143
  @config['mauth_api_version'] = given_config['mauth_api_version']
139
144
  @config['logger'] = given_config['logger'] || begin
140
- if Object.const_defined?('Rails') && Rails.logger
145
+ if Object.const_defined?(:Rails) && Rails.logger
141
146
  Rails.logger
142
147
  else
143
148
  require 'logger'
@@ -151,26 +156,25 @@ module MAuth
151
156
  request_config.merge!(symbolize_keys(given_config['faraday_options'])) if given_config['faraday_options']
152
157
  @config['faraday_options'] = { request: request_config } || {}
153
158
  @config['ssl_certs_path'] = given_config['ssl_certs_path'] if given_config['ssl_certs_path']
154
- @config['v2_only_authenticate'] = given_config['v2_only_authenticate'].to_s.downcase == 'true'
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'
159
+ @config['v2_only_authenticate'] = given_config['v2_only_authenticate'].to_s.casecmp('true').zero?
160
+ @config['v2_only_sign_requests'] = given_config['v2_only_sign_requests'].to_s.casecmp('true').zero?
161
+ @config['disable_fallback_to_v1_on_v2_failure'] =
162
+ given_config['disable_fallback_to_v1_on_v2_failure'].to_s.casecmp('true').zero?
163
+ @config['v1_only_sign_requests'] = given_config['v1_only_sign_requests'].to_s.casecmp('true').zero?
158
164
 
159
165
  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"
166
+ raise MAuth::Client::ConfigurationError, 'v2_only_sign_requests and v1_only_sign_requests may not both be true'
161
167
  end
162
168
 
163
169
  # if 'authenticator' was given, don't override that - including if it was given as nil / false
164
170
  if given_config.key?('authenticator')
165
171
  @config['authenticator'] = given_config['authenticator']
172
+ elsif client_app_uuid && private_key
173
+ @config['authenticator'] = LocalAuthenticator
174
+ # MAuth::Client can authenticate locally if it's provided a client_app_uuid and private_key
166
175
  else
167
- if client_app_uuid && private_key
168
- # MAuth::Client can authenticate locally if it's provided a client_app_uuid and private_key
169
- @config['authenticator'] = LocalAuthenticator
170
- else
171
- # otherwise, it will authenticate remotely (requests only)
172
- @config['authenticator'] = RemoteRequestAuthenticator
173
- end
176
+ # otherwise, it will authenticate remotely (requests only)
177
+ @config['authenticator'] = RemoteRequestAuthenticator
174
178
  end
175
179
  extend @config['authenticator'] if @config['authenticator']
176
180
  end
@@ -184,11 +188,11 @@ module MAuth
184
188
  end
185
189
 
186
190
  def mauth_baseurl
187
- @config['mauth_baseurl'] || raise(MAuth::Client::ConfigurationError, "no configured mauth_baseurl!")
191
+ @config['mauth_baseurl'] || raise(MAuth::Client::ConfigurationError, 'no configured mauth_baseurl!')
188
192
  end
189
193
 
190
194
  def mauth_api_version
191
- @config['mauth_api_version'] || raise(MAuth::Client::ConfigurationError, "no configured mauth_api_version!")
195
+ @config['mauth_api_version'] || raise(MAuth::Client::ConfigurationError, 'no configured mauth_api_version!')
192
196
  end
193
197
 
194
198
  def private_key
@@ -235,7 +239,7 @@ module MAuth
235
239
 
236
240
  # Changes all keys in the top level of the hash to symbols. Does not affect nested hashes inside this one.
237
241
  def symbolize_keys(hash)
238
- hash.keys.each do |key|
242
+ hash.keys.each do |key| # rubocop:disable Style/HashEachMethods
239
243
  hash[(key.to_sym rescue key) || key] = hash.delete(key)
240
244
  end
241
245
  hash
@@ -243,7 +247,7 @@ module MAuth
243
247
  end
244
248
 
245
249
  module ConfigFile
246
- GITHUB_URL = 'https://github.com/mdsol/mauth-client-ruby'.freeze
250
+ GITHUB_URL = 'https://github.com/mdsol/mauth-client-ruby'
247
251
  @config = {}
248
252
 
249
253
  def self.load(path)
@@ -251,12 +255,17 @@ module MAuth
251
255
  raise "File #{path} not found. Please visit #{GITHUB_URL} for details."
252
256
  end
253
257
 
254
- @config[path] ||= YAML.load_file(path)
258
+ @config[path] ||= yaml_safe_load_file(path)
255
259
  unless @config[path]
256
260
  raise "File #{path} does not contain proper YAML information. Visit #{GITHUB_URL} for details."
257
261
  end
258
262
 
259
263
  @config[path]
260
264
  end
265
+
266
+ def self.yaml_safe_load_file(path)
267
+ yml_data = File.read(path)
268
+ YAML.safe_load(yml_data, aliases: true)
269
+ end
261
270
  end
262
271
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Hash
2
4
  # like stringify_keys, but does not attempt to stringify anything other than Symbols.
3
5
  # other keys are left alone.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dice_bag'
2
4
 
3
5
  class MauthTemplate < DiceBag::AvailableTemplates
@@ -14,6 +16,6 @@ class MauthInitializerTemplate < DiceBag::AvailableTemplates
14
16
  end
15
17
 
16
18
  def templates
17
- [File.join(File.dirname(__FILE__), 'mauth.rb.dice')] if Object.const_defined?('Rails')
19
+ [File.join(File.dirname(__FILE__), 'mauth.rb.dice')] if Object.const_defined?(:Rails)
18
20
  end
19
21
  end
data/lib/mauth/errors.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MAuth
2
4
  # mAuth client was unable to verify the authenticity of a signed object (this does NOT mean the
3
5
  # object is inauthentic). typically due to a failure communicating with the mAuth service, in
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mauth/rack'
2
4
 
3
5
  module MAuth
@@ -14,30 +16,32 @@ module MAuth
14
16
  # (rather than switching to this fake one), as all this does is add those keys to the request env.
15
17
  class RequestAuthenticationFaker < MAuth::Rack::RequestAuthenticator
16
18
  class << self
17
- def is_authentic?
19
+ def is_authentic? # rubocop:disable Naming/PredicateName
18
20
  @is_authentic.nil? ? true : @is_authentic
19
21
  end
20
22
 
21
- def authentic=(is_auth = true)
23
+ def authentic=(is_auth = true) # rubocop:disable Style/OptionalBooleanParameter
22
24
  @is_authentic = is_auth
23
25
  end
24
26
  end
25
27
 
26
28
  def call(env)
27
29
  retval = if should_authenticate?(env)
28
- mauth_request = MAuth::Rack::Request.new(env)
29
- env['mauth.protocol_version'] = mauth_request.protocol_version
30
+ mauth_request = MAuth::Rack::Request.new(env)
31
+ env['mauth.protocol_version'] = mauth_request.protocol_version
30
32
 
31
- if self.class.is_authentic?
32
- @app.call(env.merge!('mauth.app_uuid' => mauth_request.signature_app_uuid, 'mauth.authentic' => true))
33
- else
34
- response_for_inauthentic_request(env)
35
- end
36
- else
37
- @app.call(env)
38
- end
33
+ if self.class.is_authentic?
34
+ @app.call(env.merge!('mauth.app_uuid' => mauth_request.signature_app_uuid,
35
+ 'mauth.authentic' => true))
36
+ else
37
+ response_for_inauthentic_request(env)
38
+ end
39
+ else
40
+ @app.call(env)
41
+ end
39
42
 
40
- # ensure that the next request is marked authenic unless the consumer of this middleware explicitly deems otherwise
43
+ # ensure that the next request is marked authenic unless the consumer of this middleware explicitly deems
44
+ # otherwise
41
45
  self.class.authentic = true
42
46
 
43
47
  retval