mauth-client 6.4.3 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,133 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # methods common to RemoteRequestAuthenticator and LocalAuthenticator
4
-
5
- module MAuth
6
- class Client
7
- module AuthenticatorBase
8
- ALLOWED_DRIFT_SECONDS = 300
9
-
10
- # takes an incoming request or response object, and returns whether
11
- # the object is authentic according to its signature.
12
- def authentic?(object)
13
- log_authentication_request(object)
14
- begin
15
- authenticate!(object)
16
- true
17
- rescue InauthenticError, MAuthNotPresent, MissingV2Error
18
- false
19
- end
20
- end
21
-
22
- # raises InauthenticError unless the given object is authentic. Will only
23
- # authenticate with v2 if the environment variable V2_ONLY_AUTHENTICATE
24
- # is set. Otherwise will fall back to v1 when v2 authentication fails
25
- def authenticate!(object)
26
- case object.protocol_version
27
- when 2
28
- begin
29
- authenticate_v2!(object)
30
- rescue InauthenticError => e
31
- raise e if v2_only_authenticate?
32
- raise e if disable_fallback_to_v1_on_v2_failure?
33
-
34
- object.fall_back_to_mws_signature_info
35
- raise e unless object.signature
36
-
37
- log_authentication_request(object)
38
- authenticate_v1!(object)
39
- logger.warn('Completed successful authentication attempt after fallback to v1')
40
- end
41
- when 1
42
- if v2_only_authenticate?
43
- # If v2 is required but not present and v1 is present we raise MissingV2Error
44
- msg = 'This service requires mAuth v2 mcc-authentication header but only v1 x-mws-authentication is present'
45
- logger.error(msg)
46
- raise MissingV2Error, msg
47
- end
48
-
49
- authenticate_v1!(object)
50
- else
51
- sub_str = v2_only_authenticate? ? '' : 'X-MWS-Authentication header is blank, '
52
- msg = "Authentication Failed. No mAuth signature present; #{sub_str}MCC-Authentication header is blank."
53
- logger.warn("mAuth signature not present on #{object.class}. Exception: #{msg}")
54
- raise MAuthNotPresent, msg
55
- end
56
- end
57
-
58
- private
59
-
60
- # NOTE: This log is likely consumed downstream and the contents SHOULD NOT
61
- # be changed without a thorough review of downstream consumers.
62
- def log_authentication_request(object)
63
- object_app_uuid = object.signature_app_uuid || '[none provided]'
64
- object_token = object.signature_token || '[none provided]'
65
- logger.info(
66
- 'Mauth-client attempting to authenticate request from app with mauth' \
67
- " app uuid #{object_app_uuid} to app with mauth app uuid #{client_app_uuid}" \
68
- " using version #{object_token}."
69
- )
70
- end
71
-
72
- def log_inauthentic(object, message)
73
- logger.error("mAuth signature authentication failed for #{object.class}. Exception: #{message}")
74
- end
75
-
76
- def time_within_valid_range!(object, time_signed, now = Time.now)
77
- return if (-ALLOWED_DRIFT_SECONDS..ALLOWED_DRIFT_SECONDS).cover?(now.to_i - time_signed)
78
-
79
- msg = "Time verification failed. #{time_signed} not within #{ALLOWED_DRIFT_SECONDS} of #{now}"
80
- log_inauthentic(object, msg)
81
- raise InauthenticError, msg
82
- end
83
-
84
- # V1 helpers
85
- def authenticate_v1!(object)
86
- time_valid_v1!(object)
87
- token_valid_v1!(object)
88
- signature_valid_v1!(object)
89
- end
90
-
91
- def time_valid_v1!(object)
92
- if object.x_mws_time.nil?
93
- msg = 'Time verification failed. No x-mws-time present.'
94
- log_inauthentic(object, msg)
95
- raise InauthenticError, msg
96
- end
97
- time_within_valid_range!(object, object.x_mws_time.to_i)
98
- end
99
-
100
- def token_valid_v1!(object)
101
- return if object.signature_token == MWS_TOKEN
102
-
103
- msg = "Token verification failed. Expected #{MWS_TOKEN}; token was #{object.signature_token}"
104
- log_inauthentic(object, msg)
105
- raise InauthenticError, msg
106
- end
107
-
108
- # V2 helpers
109
- def authenticate_v2!(object)
110
- time_valid_v2!(object)
111
- token_valid_v2!(object)
112
- signature_valid_v2!(object)
113
- end
114
-
115
- def time_valid_v2!(object)
116
- if object.mcc_time.nil?
117
- msg = 'Time verification failed. No MCC-Time present.'
118
- log_inauthentic(object, msg)
119
- raise InauthenticError, msg
120
- end
121
- time_within_valid_range!(object, object.mcc_time.to_i)
122
- end
123
-
124
- def token_valid_v2!(object)
125
- return if object.signature_token == MWSV2_TOKEN
126
-
127
- msg = "Token verification failed. Expected #{MWSV2_TOKEN}; token was #{object.signature_token}"
128
- log_inauthentic(object, msg)
129
- raise InauthenticError, msg
130
- end
131
- end
132
- end
133
- end
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # methods for remotely authenticating a request by sending it to the mauth service
4
-
5
- module MAuth
6
- class Client
7
- module RemoteRequestAuthenticator
8
- private
9
-
10
- # takes an incoming request object (no support for responses currently), and errors if the
11
- # object is not authentic according to its signature
12
- def signature_valid_v1!(object)
13
- unless object.is_a?(MAuth::Request)
14
- raise ArgumentError,
15
- "Remote Authenticator can only authenticate requests; received #{object.inspect}"
16
- end
17
-
18
- authentication_ticket = {
19
- 'verb' => object.attributes_for_signing[:verb],
20
- 'app_uuid' => object.signature_app_uuid,
21
- 'client_signature' => object.signature,
22
- 'request_url' => object.attributes_for_signing[:request_url],
23
- 'request_time' => object.x_mws_time,
24
- 'b64encoded_body' => Base64.encode64(object.attributes_for_signing[:body] || '')
25
- }
26
- make_mauth_request(authentication_ticket)
27
- end
28
-
29
- def signature_valid_v2!(object)
30
- unless object.is_a?(MAuth::Request)
31
- msg = "Remote Authenticator can only authenticate requests; received #{object.inspect}"
32
- raise ArgumentError, msg
33
- end
34
-
35
- authentication_ticket = {
36
- verb: object.attributes_for_signing[:verb],
37
- app_uuid: object.signature_app_uuid,
38
- client_signature: object.signature,
39
- request_url: object.attributes_for_signing[:request_url],
40
- request_time: object.mcc_time,
41
- b64encoded_body: Base64.encode64(object.attributes_for_signing[:body] || ''),
42
- query_string: object.attributes_for_signing[:query_string],
43
- token: object.signature_token
44
- }
45
- make_mauth_request(authentication_ticket)
46
- end
47
-
48
- def make_mauth_request(authentication_ticket)
49
- begin
50
- request_body = JSON.generate(authentication_ticket: authentication_ticket)
51
- response = mauth_connection.post("/mauth/#{mauth_api_version}/authentication_tickets.json", request_body)
52
- rescue ::Faraday::ConnectionFailed, ::Faraday::TimeoutError => e
53
- msg = "mAuth service did not respond; received #{e.class}: #{e.message}"
54
- logger.error("Unable to authenticate with MAuth. Exception #{msg}")
55
- raise UnableToAuthenticateError, msg
56
- end
57
- case response.status
58
- when 200..299
59
- nil
60
- when 412, 404
61
- # the mAuth service responds with 412 when the given request is not authentically signed.
62
- # older versions of the mAuth service respond with 404 when the given app_uuid
63
- # does not exist, which is also considered to not be authentically signed. newer
64
- # versions of the service respond 412 in all cases, so the 404 check may be removed
65
- # when the old version of the mAuth service is out of service.
66
- raise InauthenticError, "The mAuth service responded with #{response.status}: #{response.body}"
67
- else
68
- mauth_service_response_error(response)
69
- end
70
- end
71
-
72
- def mauth_connection
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
81
- end
82
- end
83
- end
84
- end
85
- end
@@ -1,12 +0,0 @@
1
- <%= warning.as_yaml_comment %>
2
-
3
- MAUTH_CONF = MAuth::Client.default_config
4
- require 'mauth/rack'
5
- # ResponseSigner OPTIONAL; only use if you are registered in mauth service
6
- Rails.application.config.middleware.insert_after Rack::Runtime, MAuth::Rack::ResponseSigner, MAUTH_CONF
7
- if Rails.env.test? || Rails.env.development?
8
- require 'mauth/fake/rack'
9
- Rails.application.config.middleware.insert_after MAuth::Rack::ResponseSigner, MAuth::Rack::RequestAuthenticationFaker, MAUTH_CONF
10
- else
11
- Rails.application.config.middleware.insert_after MAuth::Rack::ResponseSigner, MAuth::Rack::RequestAuthenticatorNoAppStatus, MAUTH_CONF
12
- end
@@ -1,18 +0,0 @@
1
- <%= warning.as_yaml_comment %>
2
-
3
- common: &common
4
- mauth_baseurl: <%= configured.mauth_url! || 'http://localhost:7000' %>
5
- mauth_api_version: v1
6
- app_uuid: <%= configured.mauth_app_uuid! || 'fb17460e-9868-11e1-8399-0090f5ccb4d3' %>
7
- private_key_file: config/mauth_key
8
- v2_only_authenticate: <%= configured.v2_only_authenticate || 'false' %>
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' %>
12
-
13
- production:
14
- <<: *common
15
- development:
16
- <<: *common
17
- test:
18
- <<: *common
@@ -1 +0,0 @@
1
- <%= ensure_is_private_key(configured.mauth_private_key! || generate_private_key.to_s) %>
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dice_bag'
4
-
5
- class MauthTemplate < DiceBag::AvailableTemplates
6
- def templates
7
- ['mauth.yml.dice', 'mauth_key.dice'].map do |template|
8
- File.join(File.dirname(__FILE__), template)
9
- end
10
- end
11
- end
12
-
13
- class MauthInitializerTemplate < DiceBag::AvailableTemplates
14
- def templates_location
15
- 'config/initializers'
16
- end
17
-
18
- def templates
19
- [File.join(File.dirname(__FILE__), 'mauth.rb.dice')] if Object.const_defined?(:Rails)
20
- end
21
- end