@@ -11,6 +11,8 @@ module RubySaml
11
11
# SAML2 Authentication Response. SAML Response
12
12
#
13
13
class Response < SamlMessage
14
+ include ErrorHandling
15
+
14
16
ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
15
17
PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
16
18
DSIG = "http://www.w3.org/2000/09/xmldsig#"
@@ -21,9 +23,6 @@ class Response < SamlMessage
21
23
# OneLogin::RubySaml::Settings Toolkit settings
22
24
attr_accessor :settings
23
25
24
- # Array with the causes [Array of strings]
25
- attr_accessor :errors
26
-
27
26
attr_reader :document
28
27
attr_reader :decrypted_document
29
28
attr_reader :response
@@ -39,11 +38,10 @@ class Response < SamlMessage
39
38
# or :matches_request_id that will validate that the response matches the ID of the request,
40
39
# or skip the subject confirmation validation with the :skip_subject_confirmation option
41
40
def initialize ( response , options = { } )
42
- @errors = [ ]
43
-
44
41
raise ArgumentError . new ( "Response cannot be nil" ) if response . nil?
45
- @options = options
46
42
43
+ @errors = [ ]
44
+ @options = options
47
45
@soft = true
48
46
unless options [ :settings ] . nil?
49
47
@settings = options [ :settings ]
@@ -60,23 +58,12 @@ def initialize(response, options = {})
60
58
end
61
59
end
62
60
63
- # Append the cause to the errors array, and based on the value of soft, return false or raise
64
- # an exception
65
- def append_error ( error_msg )
66
- @errors << error_msg
67
- return soft ? false : validation_error ( error_msg )
68
- end
69
-
70
- # Reset the errors array
71
- def reset_errors!
72
- @errors = [ ]
73
- end
74
-
75
61
# Validates the SAML Response with the default values (soft = true)
62
+ # @param collect_errors [Boolean] Stop validation when first error appears or keep validating. (if soft=true)
76
63
# @return [Boolean] TRUE if the SAML Response is valid
77
64
#
78
- def is_valid?
79
- validate
65
+ def is_valid? ( collect_errors = false )
66
+ validate ( collect_errors )
80
67
end
81
68
82
69
# @return [String] the NameID provided by the SAML response from the IdP.
@@ -297,28 +284,48 @@ def allowed_clock_drift
297
284
private
298
285
299
286
# Validates the SAML Response (calls several validation methods)
287
+ # @param collect_errors [Boolean] Stop validation when first error appears or keep validating. (if soft=true)
300
288
# @return [Boolean] True if the SAML Response is valid, otherwise False if soft=True
301
289
# @raise [ValidationError] if soft == false and validation fails
302
290
#
303
- def validate
291
+ def validate ( collect_errors = false )
304
292
reset_errors!
305
293
306
- validate_response_state &&
307
- validate_version &&
308
- validate_id &&
309
- validate_success_status &&
310
- validate_num_assertion &&
311
- validate_no_encrypted_attributes &&
312
- validate_signed_elements &&
313
- validate_structure &&
314
- validate_in_response_to &&
315
- validate_conditions &&
316
- validate_audience &&
317
- validate_destination &&
318
- validate_issuer &&
319
- validate_session_expiration &&
320
- validate_subject_confirmation &&
321
- validate_signature
294
+ if collect_errors
295
+ return false unless validate_response_state
296
+ validate_version
297
+ validate_id
298
+ validate_success_status
299
+ validate_num_assertion
300
+ validate_no_encrypted_attributes
301
+ validate_signed_elements
302
+ validate_structure
303
+ validate_in_response_to
304
+ validate_conditions
305
+ validate_audience
306
+ validate_issuer
307
+ validate_session_expiration
308
+ validate_subject_confirmation
309
+ validate_signature
310
+ @errors . empty?
311
+ else
312
+ validate_response_state &&
313
+ validate_version &&
314
+ validate_id &&
315
+ validate_success_status &&
316
+ validate_num_assertion &&
317
+ validate_no_encrypted_attributes &&
318
+ validate_signed_elements &&
319
+ validate_structure &&
320
+ validate_in_response_to &&
321
+ validate_conditions &&
322
+ validate_audience &&
323
+ validate_destination &&
324
+ validate_issuer &&
325
+ validate_session_expiration &&
326
+ validate_subject_confirmation &&
327
+ validate_signature
328
+ end
322
329
end
323
330
324
331
@@ -708,7 +715,7 @@ def xpath_from_signed_assertion(subelt=nil)
708
715
#
709
716
def generate_decrypted_document
710
717
if settings . nil? || !settings . get_sp_key
711
- validation_error ( 'An EncryptedAssertion found and no SP private key found on the settings to decrypt it. Be sure you provided the :settings parameter at the initialize method' )
718
+ raise ValidationError . new ( 'An EncryptedAssertion found and no SP private key found on the settings to decrypt it. Be sure you provided the :settings parameter at the initialize method' )
712
719
end
713
720
714
721
# Marshal at Ruby 1.8.7 throw an Exception
@@ -774,7 +781,7 @@ def decrypt_nameid(encryptedid_node)
774
781
#
775
782
def decrypt_element ( encrypt_node , rgrex )
776
783
if settings . nil? || !settings . get_sp_key
777
- return validation_error ( 'An ' + encrypt_node . name + ' found and no SP private key found on the settings to decrypt it' )
784
+ raise ValidationError . new ( 'An ' + encrypt_node . name + ' found and no SP private key found on the settings to decrypt it' )
778
785
end
779
786
780
787
elem_plaintext = OneLogin ::RubySaml ::Utils . decrypt_data ( encrypt_node , settings . get_sp_key )
0 commit comments