ruby-saml 0.8.16 → 0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -6
  4. data/Gemfile +2 -12
  5. data/README.md +363 -35
  6. data/Rakefile +14 -0
  7. data/changelog.md +22 -9
  8. data/lib/onelogin/ruby-saml/attribute_service.rb +34 -0
  9. data/lib/onelogin/ruby-saml/attributes.rb +26 -64
  10. data/lib/onelogin/ruby-saml/authrequest.rb +47 -89
  11. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +87 -0
  12. data/lib/onelogin/ruby-saml/logoutrequest.rb +34 -93
  13. data/lib/onelogin/ruby-saml/logoutresponse.rb +25 -24
  14. data/lib/onelogin/ruby-saml/metadata.rb +46 -16
  15. data/lib/onelogin/ruby-saml/response.rb +62 -322
  16. data/lib/onelogin/ruby-saml/saml_message.rb +78 -0
  17. data/lib/onelogin/ruby-saml/settings.rb +54 -121
  18. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +26 -61
  19. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +27 -84
  20. data/lib/onelogin/ruby-saml/utils.rb +32 -199
  21. data/lib/onelogin/ruby-saml/version.rb +1 -1
  22. data/lib/ruby-saml.rb +5 -2
  23. data/lib/schemas/{saml20assertion_schema.xsd → saml-schema-assertion-2.0.xsd} +283 -283
  24. data/lib/schemas/saml-schema-authn-context-2.0.xsd +23 -0
  25. data/lib/schemas/saml-schema-authn-context-types-2.0.xsd +821 -0
  26. data/lib/schemas/saml-schema-metadata-2.0.xsd +339 -0
  27. data/lib/schemas/{saml20protocol_schema.xsd → saml-schema-protocol-2.0.xsd} +302 -302
  28. data/lib/schemas/sstc-metadata-attr.xsd +35 -0
  29. data/lib/schemas/sstc-saml-attribute-ext.xsd +25 -0
  30. data/lib/schemas/sstc-saml-metadata-algsupport-v1.0.xsd +41 -0
  31. data/lib/schemas/sstc-saml-metadata-ui-v1.0.xsd +89 -0
  32. data/lib/schemas/{xenc_schema.xsd → xenc-schema.xsd} +1 -11
  33. data/lib/schemas/xml.xsd +287 -0
  34. data/lib/schemas/{xmldsig_schema.xsd → xmldsig-core-schema.xsd} +0 -9
  35. data/lib/xml_security.rb +83 -235
  36. data/ruby-saml.gemspec +1 -0
  37. data/test/idp_metadata_parser_test.rb +54 -0
  38. data/test/logoutrequest_test.rb +68 -144
  39. data/test/logoutresponse_test.rb +43 -25
  40. data/test/metadata_test.rb +87 -0
  41. data/test/request_test.rb +103 -90
  42. data/test/response_test.rb +181 -471
  43. data/test/responses/idp_descriptor.xml +3 -0
  44. data/test/responses/logoutresponse_fixtures.rb +5 -5
  45. data/test/responses/response_no_cert_and_encrypted_attrs.xml +29 -0
  46. data/test/responses/response_with_multiple_attribute_values.xml +1 -1
  47. data/test/responses/slo_request.xml +4 -0
  48. data/test/settings_test.rb +25 -112
  49. data/test/slo_logoutrequest_test.rb +41 -44
  50. data/test/slo_logoutresponse_test.rb +87 -167
  51. data/test/test_helper.rb +27 -102
  52. data/test/xml_security_test.rb +114 -337
  53. metadata +34 -84
  54. data/lib/onelogin/ruby-saml/setting_error.rb +0 -6
  55. data/test/certificates/certificate.der +0 -0
  56. data/test/certificates/formatted_certificate +0 -14
  57. data/test/certificates/formatted_chained_certificate +0 -42
  58. data/test/certificates/formatted_private_key +0 -12
  59. data/test/certificates/formatted_rsa_private_key +0 -12
  60. data/test/certificates/invalid_certificate1 +0 -1
  61. data/test/certificates/invalid_certificate2 +0 -1
  62. data/test/certificates/invalid_certificate3 +0 -12
  63. data/test/certificates/invalid_chained_certificate1 +0 -1
  64. data/test/certificates/invalid_private_key1 +0 -1
  65. data/test/certificates/invalid_private_key2 +0 -1
  66. data/test/certificates/invalid_private_key3 +0 -10
  67. data/test/certificates/invalid_rsa_private_key1 +0 -1
  68. data/test/certificates/invalid_rsa_private_key2 +0 -1
  69. data/test/certificates/invalid_rsa_private_key3 +0 -10
  70. data/test/certificates/ruby-saml-2.crt +0 -15
  71. data/test/requests/logoutrequest_fixtures.rb +0 -47
  72. data/test/responses/encrypted_new_attack.xml.base64 +0 -1
  73. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  74. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  75. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  76. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  77. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  78. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  79. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  80. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  81. data/test/responses/response_with_concealed_signed_assertion.xml +0 -51
  82. data/test/responses/response_with_doubled_signed_assertion.xml +0 -49
  83. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  84. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  85. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  86. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  87. data/test/responses/response_wrapped.xml.base64 +0 -150
  88. data/test/responses/valid_response.xml.base64 +0 -1
  89. data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
  90. data/test/utils_test.rb +0 -231
@@ -1,30 +1,30 @@
1
1
  require "xml_security"
2
2
  require "time"
3
3
  require "nokogiri"
4
- require "onelogin/ruby-saml/utils"
5
- require 'onelogin/ruby-saml/attributes'
6
4
 
7
5
  # Only supports SAML 2.0
8
6
  module OneLogin
9
7
  module RubySaml
10
8
 
11
- class Response
9
+ class Response < SamlMessage
12
10
  ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
13
11
  PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
14
12
  DSIG = "http://www.w3.org/2000/09/xmldsig#"
15
13
 
16
14
  # TODO: This should probably be ctor initialized too... WDYT?
17
15
  attr_accessor :settings
16
+ attr_accessor :errors
18
17
 
19
18
  attr_reader :options
20
19
  attr_reader :response
21
20
  attr_reader :document
22
21
 
23
22
  def initialize(response, options = {})
23
+ @errors = []
24
24
  raise ArgumentError.new("Response cannot be nil") if response.nil?
25
25
  @options = options
26
- @response = OneLogin::RubySaml::Utils.decode_raw_saml(response)
27
- @document = XMLSecurity::SignedDocument.new(@response)
26
+ @response = decode_raw_saml(response)
27
+ @document = XMLSecurity::SignedDocument.new(@response, @errors)
28
28
  end
29
29
 
30
30
  def is_valid?
@@ -35,16 +35,18 @@ module OneLogin
35
35
  validate(false)
36
36
  end
37
37
 
38
+ def errors
39
+ @errors
40
+ end
41
+
38
42
  # The value of the user identifier as designated by the initialization request response
39
43
  def name_id
40
44
  @name_id ||= begin
41
45
  node = xpath_first_from_signed_assertion('/a:Subject/a:NameID')
42
- Utils.element_text(node)
46
+ node.nil? ? nil : node.text
43
47
  end
44
48
  end
45
49
 
46
- alias nameid name_id
47
-
48
50
  def sessionindex
49
51
  @sessionindex ||= begin
50
52
  node = xpath_first_from_signed_assertion('/a:AuthnStatement')
@@ -52,9 +54,9 @@ module OneLogin
52
54
  end
53
55
  end
54
56
 
55
- # Gets the Attributes from the AttributeStatement element.
56
- #
57
+ # Returns OneLogin::RubySaml::Attributes enumerable collection.
57
58
  # All attributes can be iterated over +attributes.each+ or returned as array by +attributes.all+
59
+ #
58
60
  # For backwards compatibility ruby-saml returns by default only the first value for a given attribute with
59
61
  # attributes['name']
60
62
  # To get all of the attributes, use:
@@ -63,36 +65,24 @@ module OneLogin
63
65
  # OneLogin::RubySaml::Attributes.single_value_compatibility = false
64
66
  # Now this will return an array:
65
67
  # attributes['name']
66
- #
67
- # @return [Attributes] OneLogin::RubySaml::Attributes enumerable collection.
68
- #
69
68
  def attributes
70
69
  @attr_statements ||= begin
71
70
  attributes = Attributes.new
72
71
 
73
- stmt_elements = xpath_from_signed_assertion('/a:AttributeStatement')
74
- stmt_elements.each do |stmt_element|
75
- stmt_element.elements.each do |attr_element|
76
- name = attr_element.attributes["Name"]
77
- values = attr_element.elements.collect{|e|
78
- if (e.elements.nil? || e.elements.size == 0)
79
- # SAMLCore requires that nil AttributeValues MUST contain xsi:nil XML attribute set to "true" or "1"
80
- # otherwise the value is to be regarded as empty.
81
- ["true", "1"].include?(e.attributes['xsi:nil']) ? nil : Utils.element_text(e)
82
- # explicitly support saml2:NameID with saml2:NameQualifier if supplied in attributes
83
- # this is useful for allowing eduPersonTargetedId to be passed as an opaque identifier to use to
84
- # identify the subject in an SP rather than email or other less opaque attributes
85
- # NameQualifier, if present is prefixed with a "/" to the value
86
- else
87
- REXML::XPath.match(e,'a:NameID', { "a" => ASSERTION }).collect{|n|
88
- (n.attributes['NameQualifier'] ? n.attributes['NameQualifier'] +"/" : '') + Utils.element_text(n)
89
- }
90
- end
91
- }
92
-
93
- attributes.add(name, values.flatten)
94
- end
72
+ stmt_element = xpath_first_from_signed_assertion('/a:AttributeStatement')
73
+ return attributes if stmt_element.nil?
74
+
75
+ stmt_element.elements.each do |attr_element|
76
+ name = attr_element.attributes["Name"]
77
+ values = attr_element.elements.collect{|e|
78
+ # SAMLCore requires that nil AttributeValues MUST contain xsi:nil XML attribute set to "true" or "1"
79
+ # otherwise the value is to be regarded as empty.
80
+ ["true", "1"].include?(e.attributes['xsi:nil']) ? nil : e.text.to_s
81
+ }
82
+
83
+ attributes.add(name, values)
95
84
  end
85
+
96
86
  attributes
97
87
  end
98
88
  end
@@ -113,6 +103,13 @@ module OneLogin
113
103
  end
114
104
  end
115
105
 
106
+ def status_message
107
+ @status_message ||= begin
108
+ node = REXML::XPath.first(document, "/p:Response/p:Status/p:StatusMessage", { "p" => PROTOCOL, "a" => ASSERTION })
109
+ node.text if node
110
+ end
111
+ end
112
+
116
113
  # Conditions (if any) for the assertion to run
117
114
  def conditions
118
115
  @conditions ||= xpath_first_from_signed_assertion('/a:Conditions')
@@ -130,223 +127,43 @@ module OneLogin
130
127
  @issuer ||= begin
131
128
  node = REXML::XPath.first(document, "/p:Response/a:Issuer", { "p" => PROTOCOL, "a" => ASSERTION })
132
129
  node ||= xpath_first_from_signed_assertion('/a:Issuer')
133
- Utils.element_text(node)
134
- end
135
- end
136
-
137
- # Gets the Issuers (from Response and Assertion).
138
- # (returns the first node that matches the supplied xpath from the Response and from the Assertion)
139
- # @return [Array] Array with the Issuers (REXML::Element)
140
- #
141
- def issuers
142
- @issuers ||= begin
143
- issuer_response_nodes = REXML::XPath.match(
144
- document,
145
- "/p:Response/a:Issuer",
146
- { "p" => PROTOCOL, "a" => ASSERTION }
147
- )
148
-
149
- unless issuer_response_nodes.size == 1
150
- error_msg = "Issuer of the Response not found or multiple."
151
- raise ValidationError.new(error_msg)
152
- end
153
-
154
- issuer_assertion_nodes = xpath_from_signed_assertion("/a:Issuer")
155
- unless issuer_assertion_nodes.size == 1
156
- error_msg = "Issuer of the Assertion not found or multiple."
157
- raise ValidationError.new(error_msg)
158
- end
159
-
160
- nodes = issuer_response_nodes + issuer_assertion_nodes
161
- nodes.map { |node| Utils.element_text(node) }.compact.uniq
162
- end
163
- end
164
-
165
- # @return [Array] The Audience elements from the Contitions of the SAML Response.
166
- #
167
- def audiences
168
- @audiences ||= begin
169
- nodes = xpath_from_signed_assertion('/a:Conditions/a:AudienceRestriction/a:Audience')
170
- nodes.map { |node| Utils.element_text(node) }.reject(&:empty?)
130
+ node.nil? ? nil : node.text
171
131
  end
172
132
  end
173
133
 
174
134
  private
175
135
 
176
- def validation_error(message)
177
- raise ValidationError.new(message)
178
- end
179
-
180
136
  def validate(soft = true)
181
- validate_structure(soft) &&
182
- validate_success_status(soft) &&
183
- validate_num_assertion &&
184
- validate_signed_elements(soft) &&
185
- validate_response_state(soft) &&
186
- validate_conditions(soft) &&
187
- validate_audience(soft) &&
188
- validate_issuer(soft) &&
189
- validate_signature(soft) &&
190
- success?
137
+ valid_saml?(document, soft) &&
138
+ validate_response_state(soft) &&
139
+ validate_conditions(soft) &&
140
+ validate_issuer(soft) &&
141
+ document.validate_document(get_fingerprint, soft) &&
142
+ validate_success_status(soft)
191
143
  end
192
144
 
193
- # Validates that the SAML Response only contains a single Assertion (encrypted or not).
194
- # @return [Boolean] True if the SAML Response contains one unique Assertion, otherwise False
195
- #
196
- def validate_num_assertion(soft = true)
197
- assertions = REXML::XPath.match(
198
- document,
199
- "//a:Assertion",
200
- { "a" => ASSERTION }
201
- )
202
- encrypted_assertions = REXML::XPath.match(
203
- document,
204
- "//a:EncryptedAssertion",
205
- { "a" => ASSERTION }
206
- )
207
-
208
- unless assertions.size + encrypted_assertions.size == 1
209
- return soft ? false : validation_error("SAML Response must contain 1 assertion")
210
- end
211
-
212
- true
213
- end
214
-
215
- # Validates the Signed elements
216
- # @return [Boolean] True if there is 1 or 2 Elements signed in the SAML Response
217
- # an are a Response or an Assertion Element, otherwise False if soft=True
218
- #
219
- def validate_signed_elements(soft)
220
- signature_nodes = REXML::XPath.match(
221
- document,
222
- "//ds:Signature",
223
- {"ds"=>DSIG}
224
- )
225
- signed_elements = []
226
- verified_seis = []
227
- verified_ids = []
228
- signature_nodes.each do |signature_node|
229
- signed_element = signature_node.parent.name
230
- if signed_element != 'Response' && signed_element != 'Assertion'
231
- return soft ? false : validation_error("Invalid Signature Element '#{signed_element}'. SAML Response rejected")
232
- end
233
-
234
- if signature_node.parent.attributes['ID'].nil?
235
- return soft ? false : validation_error("Signed Element must contain an ID. SAML Response rejected")
236
- end
237
-
238
- id = signature_node.parent.attributes.get_attribute("ID").value
239
- if verified_ids.include?(id)
240
- return soft ? false : validation_error("Duplicated ID. SAML Response rejected")
241
- end
242
- verified_ids.push(id)
243
-
244
- # Check that reference URI matches the parent ID and no duplicate References or IDs
245
- ref = REXML::XPath.first(signature_node, ".//ds:Reference", {"ds"=>DSIG})
246
- if ref
247
- uri = ref.attributes.get_attribute("URI")
248
- if uri && !uri.value.empty?
249
- sei = uri.value[1..-1]
250
-
251
- unless sei == id
252
- return soft ? false : validation_error("Found an invalid Signed Element. SAML Response rejected")
253
- end
254
-
255
- if verified_seis.include?(sei)
256
- return soft ? false : validation_error("Duplicated Reference URI. SAML Response rejected")
257
- end
258
-
259
- verified_seis.push(sei)
260
- end
261
- end
262
-
263
- signed_elements << signed_element
264
- end
265
-
266
- unless signature_nodes.length < 3 && !signed_elements.empty?
267
- return soft ? false : validation_error("Found an unexpected number of Signature Element. SAML Response rejected")
268
- end
269
-
270
- true
271
- end
272
-
273
- # Validates the Status of the SAML Response
274
- # @return [Boolean] True if the SAML Response contains a Success code, otherwise False if soft == false
275
- # @raise [ValidationError] if soft == false and validation fails
276
- #
277
145
  def validate_success_status(soft = true)
278
- return true if success?
279
-
280
- return false unless soft
281
-
282
- error_msg = 'The status code of the Response was not Success'
283
- status_error_msg = OneLogin::RubySaml::Utils.status_error_msg(error_msg, status_code, status_message)
284
- return validation_error(status_error_msg)
285
- end
286
-
287
- # Checks if the Status has the "Success" code
288
- # @return [Boolean] True if the StatusCode is Sucess
289
- #
290
- def success?
291
- status_code == "urn:oasis:names:tc:SAML:2.0:status:Success"
292
- end
293
-
294
- # @return [String] StatusCode value from a SAML Response.
295
- #
296
- def status_code
297
- @status_code ||= begin
298
- nodes = REXML::XPath.match(
299
- document,
300
- "/p:Response/p:Status/p:StatusCode",
301
- { "p" => PROTOCOL }
302
- )
303
- if nodes.size == 1
304
- node = nodes[0]
305
- code = node.attributes["Value"] if node && node.attributes
306
-
307
- unless code == "urn:oasis:names:tc:SAML:2.0:status:Success"
308
- nodes = REXML::XPath.match(
309
- document,
310
- "/p:Response/p:Status/p:StatusCode/p:StatusCode",
311
- { "p" => PROTOCOL }
312
- )
313
- statuses = nodes.collect do |inner_node|
314
- inner_node.attributes["Value"]
315
- end
316
- extra_code = statuses.join(" | ")
317
- if extra_code
318
- code = "#{code} | #{extra_code}"
319
- end
320
- end
321
- code
322
- end
323
- end
324
- end
325
-
326
- # @return [String] the StatusMessage value from a SAML Response.
327
- #
328
- def status_message
329
- @status_message ||= begin
330
- nodes = REXML::XPath.match(
331
- document,
332
- "/p:Response/p:Status/p:StatusMessage",
333
- { "p" => PROTOCOL }
334
- )
335
- if nodes.size == 1
336
- Utils.element_text(nodes.first)
337
- end
146
+ if success?
147
+ true
148
+ else
149
+ soft ? false : validation_error(status_message)
338
150
  end
339
151
  end
340
152
 
341
153
  def validate_structure(soft = true)
342
154
  Dir.chdir(File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'schemas'))) do
343
- @schema = Nokogiri::XML::Schema(IO.read('saml20protocol_schema.xsd'))
155
+ @schema = Nokogiri::XML::Schema(IO.read('saml-schema-protocol-2.0.xsd'))
344
156
  @xml = Nokogiri::XML(self.document.to_s)
345
157
  end
346
158
  if soft
347
- @schema.validate(@xml).map{ return false }
159
+ @schema.validate(@xml).map{
160
+ @errors << "Schema validation failed";
161
+ return false
162
+ }
348
163
  else
349
- @schema.validate(@xml).map{ |error| validation_error("#{error.message}\n\n#{@xml.to_s}") }
164
+ @schema.validate(@xml).map{ |error| @errors << "#{error.message}\n\n#{@xml.to_s}";
165
+ validation_error("#{error.message}\n\n#{@xml.to_s}")
166
+ }
350
167
  end
351
168
  end
352
169
 
@@ -382,24 +199,13 @@ module OneLogin
382
199
  node
383
200
  end
384
201
 
385
- # Extracts all the appearances that matchs the subelt (pattern)
386
- # Search on any Assertion that is signed, or has a Response parent signed
387
- # @param subelt [String] The XPath pattern
388
- # @return [Array of REXML::Element] Return all matches
389
- #
390
- def xpath_from_signed_assertion(subelt=nil)
391
- node = REXML::XPath.match(
392
- document,
393
- "/p:Response/a:Assertion[@ID=$id]#{subelt}",
394
- { "p" => PROTOCOL, "a" => ASSERTION },
395
- { 'id' => document.signed_element_id }
396
- )
397
- node.concat( REXML::XPath.match(
398
- document,
399
- "/p:Response[@ID=$id]/a:Assertion#{subelt}",
400
- { "p" => PROTOCOL, "a" => ASSERTION },
401
- { 'id' => document.signed_element_id }
402
- ))
202
+ def get_fingerprint
203
+ if settings.idp_cert
204
+ cert = OpenSSL::X509::Certificate.new(settings.idp_cert)
205
+ Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":")
206
+ else
207
+ settings.idp_cert_fingerprint
208
+ end
403
209
  end
404
210
 
405
211
  def validate_conditions(soft = true)
@@ -409,10 +215,12 @@ module OneLogin
409
215
  now = Time.now.utc
410
216
 
411
217
  if not_before && (now + (options[:allowed_clock_drift] || 0)) < not_before
218
+ @errors << "Current time is earlier than NotBefore condition #{(now + (options[:allowed_clock_drift] || 0))} < #{not_before})"
412
219
  return soft ? false : validation_error("Current time is earlier than NotBefore condition")
413
220
  end
414
221
 
415
222
  if not_on_or_after && now >= not_on_or_after
223
+ @errors << "Current time is on or after NotOnOrAfter condition (#{now} >= #{not_on_or_after})"
416
224
  return soft ? false : validation_error("Current time is on or after NotOnOrAfter condition")
417
225
  end
418
226
 
@@ -422,64 +230,9 @@ module OneLogin
422
230
  def validate_issuer(soft = true)
423
231
  return true if settings.idp_entity_id.nil?
424
232
 
425
- begin
426
- obtained_issuers = issuers
427
- rescue ValidationError => e
428
- return soft ? false : validation_error("Error while extracting issuers")
429
- end
430
-
431
- obtained_issuers.each do |issuer|
432
- unless OneLogin::RubySaml::Utils.uri_match?(issuer, settings.idp_entity_id)
433
- error_msg = "Doesn't match the issuer, expected: <#{settings.idp_entity_id}>, but was: <#{issuer}>"
434
- return soft ? false : validation_error(error_msg)
435
- end
233
+ unless URI.parse(issuer) == URI.parse(settings.idp_entity_id)
234
+ return soft ? false : validation_error("Doesn't match the issuer, expected: <#{settings.idp_entity_id}>, but was: <#{issuer}>")
436
235
  end
437
-
438
- true
439
- end
440
-
441
- def validate_signature(soft = true)
442
- error_msg = "Invalid Signature on SAML Response"
443
-
444
- sig_elements = REXML::XPath.match(
445
- document,
446
- "/p:Response[@ID=$id]/ds:Signature]",
447
- { "p" => PROTOCOL, "ds" => DSIG },
448
- { 'id' => document.signed_element_id }
449
- )
450
-
451
- # Check signature nodes
452
- if sig_elements.nil? || sig_elements.size == 0
453
- sig_elements = REXML::XPath.match(
454
- document,
455
- "/p:Response/a:Assertion[@ID=$id]/ds:Signature",
456
- {"p" => PROTOCOL, "a" => ASSERTION, "ds"=>DSIG},
457
- { 'id' => document.signed_element_id }
458
- )
459
- end
460
-
461
- if sig_elements.size != 1
462
- if sig_elements.size == 0
463
- error_msg += ". Signed element id ##{doc.signed_element_id} is not found"
464
- else
465
- error_msg += ". Signed element id ##{doc.signed_element_id} is found more than once"
466
- end
467
- return soft ? false : validation_error(error_msg)
468
- end
469
-
470
- opts = {}
471
- opts[:fingerprint_alg] = OpenSSL::Digest::SHA1.new
472
- opts[:cert] = settings.get_idp_cert
473
- fingerprint = settings.get_fingerprint
474
-
475
- unless fingerprint
476
- return soft ? false : validation_error("No fingerprint or certificate on settings")
477
- end
478
-
479
- unless document.validate_document(fingerprint, soft, opts)
480
- return soft ? false : validation_error(error_msg)
481
- end
482
-
483
236
  true
484
237
  end
485
238
 
@@ -488,19 +241,6 @@ module OneLogin
488
241
  Time.parse(node.attributes[attribute])
489
242
  end
490
243
  end
491
-
492
- def validate_audience(soft = true)
493
- return true if audiences.empty? || settings.sp_entity_id.nil? || settings.sp_entity_id.empty?
494
-
495
- unless audiences.include? settings.sp_entity_id
496
- s = audiences.count > 1 ? 's' : '';
497
- error_msg = "Invalid Audience#{s}. The audience#{s} #{audiences.join(',')}, did not match the expected audience #{settings.sp_entity_id}"
498
- return soft ? false : validation_error(error_msg)
499
- end
500
-
501
- true
502
- end
503
-
504
244
  end
505
245
  end
506
246
  end