@@ -11,6 +11,8 @@ module RubySaml
1111 # SAML2 Authentication Response. SAML Response
1212 #
1313 class Response < SamlMessage
14+ include ErrorHandling
15+
1416 ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
1517 PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
1618 DSIG = "http://www.w3.org/2000/09/xmldsig#"
@@ -21,9 +23,6 @@ class Response < SamlMessage
2123 # OneLogin::RubySaml::Settings Toolkit settings
2224 attr_accessor :settings
2325
24- # Array with the causes [Array of strings]
25- attr_accessor :errors
26-
2726 attr_reader :document
2827 attr_reader :decrypted_document
2928 attr_reader :response
@@ -39,11 +38,10 @@ class Response < SamlMessage
3938 # or :matches_request_id that will validate that the response matches the ID of the request,
4039 # or skip the subject confirmation validation with the :skip_subject_confirmation option
4140 def initialize ( response , options = { } )
42- @errors = [ ]
43-
4441 raise ArgumentError . new ( "Response cannot be nil" ) if response . nil?
45- @options = options
4642
43+ @errors = [ ]
44+ @options = options
4745 @soft = true
4846 unless options [ :settings ] . nil?
4947 @settings = options [ :settings ]
@@ -60,23 +58,12 @@ def initialize(response, options = {})
6058 end
6159 end
6260
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-
7561 # 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)
7663 # @return [Boolean] TRUE if the SAML Response is valid
7764 #
78- def is_valid?
79- validate
65+ def is_valid? ( collect_errors = false )
66+ validate ( collect_errors )
8067 end
8168
8269 # @return [String] the NameID provided by the SAML response from the IdP.
@@ -297,28 +284,48 @@ def allowed_clock_drift
297284 private
298285
299286 # 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)
300288 # @return [Boolean] True if the SAML Response is valid, otherwise False if soft=True
301289 # @raise [ValidationError] if soft == false and validation fails
302290 #
303- def validate
291+ def validate ( collect_errors = false )
304292 reset_errors!
305293
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
322329 end
323330
324331
@@ -708,7 +715,7 @@ def xpath_from_signed_assertion(subelt=nil)
708715 #
709716 def generate_decrypted_document
710717 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' )
712719 end
713720
714721 # Marshal at Ruby 1.8.7 throw an Exception
@@ -774,7 +781,7 @@ def decrypt_nameid(encryptedid_node)
774781 #
775782 def decrypt_element ( encrypt_node , rgrex )
776783 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' )
778785 end
779786
780787 elem_plaintext = OneLogin ::RubySaml ::Utils . decrypt_data ( encrypt_node , settings . get_sp_key )
0 commit comments