ruby-saml 1.0.0 → 1.1.0

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.

Potentially problematic release.


This version of ruby-saml might be problematic. Click here for more details.

@@ -1,3 +1,4 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  rvm:
3
4
  - 1.8.7
@@ -6,6 +7,8 @@ rvm:
6
7
  - 2.1.5
7
8
  - 2.2.0
8
9
  - ree
10
+ - jruby-1.7.21
11
+ - jruby-9.0.0.0
9
12
  gemfile:
10
13
  - Gemfile
11
14
  - gemfiles/nokogiri-1.5.gemfile
@@ -15,3 +18,7 @@ matrix:
15
18
  gemfile: Gemfile
16
19
  - rvm: ree
17
20
  gemfile: Gemfile
21
+ - rvm: jruby-9.0.0.0
22
+ gemfile: gemfiles/nokogiri-1.5.gemfile
23
+ - rvm: jruby-1.7.21
24
+ gemfile: gemfiles/nokogiri-1.5.gemfile
data/README.md CHANGED
@@ -1,14 +1,18 @@
1
- # Ruby SAML [![Build Status](https://secure.travis-ci.org/onelogin/ruby-saml.png)](http://travis-ci.org/onelogin/ruby-saml)
1
+ # Ruby SAML [![Build Status](https://secure.travis-ci.org/onelogin/ruby-saml.png)](http://travis-ci.org/onelogin/ruby-saml) [![Coverage Status](https://coveralls.io/repos/onelogin/ruby-saml/badge.svg?branch=master%0A)](https://coveralls.io/r/onelogin/ruby-saml?branch=master%0A) [![Gem Version](https://badge.fury.io/rb/ruby-saml.svg)](http://badge.fury.io/rb/ruby-saml)
2
2
 
3
3
 
4
+ ## Updating from 1.0.x to 1.1.X
5
+
6
+ Version `1.1` adds some improvements on signature validation and solves some namespace conflicts.
7
+
8
+ For more details, please review [the changelog](changelog.md).
9
+
4
10
  ## Updating from 0.9.x to 1.0.X
5
11
 
6
12
  Version `1.0` is a recommended update for all Ruby SAML users as it includes security fixes.
7
13
 
8
14
  Version `1.0` adds security improvements like entity expansion limitation, more SAML message validations, and other important improvements like decrypt support.
9
15
 
10
- For more details, please review [the changelog](changelog.md).
11
-
12
16
  ### Important Changes
13
17
  Please note the `get_idp_metadata` method raises an exception when it is not able to fetch the idp metadata, so review your integration if you are using this functionality.
14
18
 
@@ -31,6 +35,8 @@ We created a demo project for Rails4 that uses the latest version of this librar
31
35
  * 1.9.x
32
36
  * 2.1.x
33
37
  * 2.2.x
38
+ * JRuby 1.7.19
39
+ * JRuby 9.0.0.0
34
40
 
35
41
  ## Adding Features, Pull Requests
36
42
  * Fork the repository
@@ -164,6 +170,13 @@ def saml_settings
164
170
  end
165
171
  ```
166
172
 
173
+ Some assertion validations can be skipped by passing parameters to OneLogin::RubySaml::Response.new(). For example, you can skip the Conditions validation or the SubjectConfirmation validations by initializing the response with different options:
174
+
175
+ ```ruby
176
+ response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_conditions: true}) # skips conditions
177
+ response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_subject_confirmation: true}) # skips subject confirmation
178
+ ```
179
+
167
180
  What's left at this point, is to wrap it all up in a controller and point the initialization and consumption URLs in OneLogin at that. A full controller example could look like this:
168
181
 
169
182
  ```ruby
@@ -394,6 +407,7 @@ Service Provider.
394
407
 
395
408
  Notice that this toolkit uses 'settings.certificate' and 'settings.private_key' for the sign and the decrypt process.
396
409
 
410
+ Enable/disable the soft mode by the settings.soft parameter. When is set false, the saml validations errors will raise an exception.
397
411
 
398
412
  ## Decrypting
399
413
 
data/Rakefile CHANGED
@@ -25,17 +25,3 @@ end
25
25
  task :test
26
26
 
27
27
  task :default => :test
28
-
29
- # require 'rake/rdoctask'
30
- # Rake::RDocTask.new do |rdoc|
31
- # if File.exist?('VERSION')
32
- # version = File.read('VERSION')
33
- # else
34
- # version = ""
35
- # end
36
-
37
- # rdoc.rdoc_dir = 'rdoc'
38
- # rdoc.title = "ruby-saml #{version}"
39
- # rdoc.rdoc_files.include('README*')
40
- # rdoc.rdoc_files.include('lib/**/*.rb')
41
- #end
@@ -1,5 +1,16 @@
1
1
  # RubySaml Changelog
2
2
 
3
+ ### 1.1.0 (October 27, 2015)
4
+ * [#273](https://github.com/onelogin/ruby-saml/pull/273) Support SAMLResponse without ds:x509certificate
5
+ * [#270](https://github.com/onelogin/ruby-saml/pull/270) Allow SAML elements to come from any namespace (at decryption process)
6
+ * [#261](https://github.com/onelogin/ruby-saml/pull/261) Allow validate_subject_confirmation Response validation to be skipped
7
+ * [#258](https://github.com/onelogin/ruby-saml/pull/258) Fix allowed_clock_drift on the validate_session_expiration test
8
+ * [#256](https://github.com/onelogin/ruby-saml/pull/256) Separate the create_authentication_xml_doc in two methods.
9
+ * [#255](https://github.com/onelogin/ruby-saml/pull/255) Refactor validate signature.
10
+ * [#254](https://github.com/onelogin/ruby-saml/pull/254) Handle empty URI references
11
+ * [#251](https://github.com/onelogin/ruby-saml/pull/251) Support qualified and unqualified NameID in attributes
12
+ * [#234](https://github.com/onelogin/ruby-saml/pull/234) Add explicit support for JRuby
13
+
3
14
  ### 1.0.0 (June 30, 2015)
4
15
  * [#247](https://github.com/onelogin/ruby-saml/pull/247) Avoid entity expansion (XEE attacks)
5
16
  * [#246](https://github.com/onelogin/ruby-saml/pull/246) Fix bug generating Logout Response (issuer was at wrong order)
@@ -87,6 +87,11 @@ module OneLogin
87
87
  # @return [String] The SAMLRequest String.
88
88
  #
89
89
  def create_authentication_xml_doc(settings)
90
+ document = create_xml_document(settings)
91
+ sign_document(document, settings)
92
+ end
93
+
94
+ def create_xml_document(settings)
90
95
  time = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
91
96
 
92
97
  request_doc = XMLSecurity::Document.new
@@ -141,14 +146,18 @@ module OneLogin
141
146
  end
142
147
  end
143
148
 
149
+ request_doc
150
+ end
151
+
152
+ def sign_document(document, settings)
144
153
  # embed signature
145
154
  if settings.security[:authn_requests_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
146
155
  private_key = settings.get_sp_key
147
156
  cert = settings.get_sp_cert
148
- request_doc.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
157
+ document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
149
158
  end
150
159
 
151
- request_doc
160
+ document
152
161
  end
153
162
 
154
163
  end
@@ -36,7 +36,8 @@ module OneLogin
36
36
  # @param options [Hash] :settings to provide the OneLogin::RubySaml::Settings object
37
37
  # Or some options for the response validation process like skip the conditions validation
38
38
  # with the :skip_conditions, or allow a clock_drift when checking dates with :allowed_clock_drift
39
- # or :matches_request_id that will validate that the response matches the ID of the request.
39
+ # or :matches_request_id that will validate that the response matches the ID of the request,
40
+ # or skip the subject confirmation validation with the :skip_subject_confirmation option
40
41
  def initialize(response, options = {})
41
42
  @errors = []
42
43
 
@@ -94,6 +95,7 @@ module OneLogin
94
95
 
95
96
  alias_method :nameid, :name_id
96
97
 
98
+
97
99
  # Gets the SessionIndex from the AuthnStatement.
98
100
  # Could be used to be stored in the local session in order
99
101
  # to be used in a future Logout Request that the SP could
@@ -131,12 +133,22 @@ module OneLogin
131
133
  stmt_element.elements.each do |attr_element|
132
134
  name = attr_element.attributes["Name"]
133
135
  values = attr_element.elements.collect{|e|
134
- # SAMLCore requires that nil AttributeValues MUST contain xsi:nil XML attribute set to "true" or "1"
135
- # otherwise the value is to be regarded as empty.
136
- ["true", "1"].include?(e.attributes['xsi:nil']) ? nil : e.text.to_s
136
+ if (e.elements.nil? || e.elements.size == 0)
137
+ # SAMLCore requires that nil AttributeValues MUST contain xsi:nil XML attribute set to "true" or "1"
138
+ # otherwise the value is to be regarded as empty.
139
+ ["true", "1"].include?(e.attributes['xsi:nil']) ? nil : e.text.to_s
140
+ # explicitly support saml2:NameID with saml2:NameQualifier if supplied in attributes
141
+ # this is useful for allowing eduPersonTargetedId to be passed as an opaque identifier to use to
142
+ # identify the subject in an SP rather than email or other less opaque attributes
143
+ # NameQualifier, if present is prefixed with a "/" to the value
144
+ else
145
+ REXML::XPath.match(e,'a:NameID', { "a" => ASSERTION }).collect{|n|
146
+ (n.attributes['NameQualifier'] ? n.attributes['NameQualifier'] +"/" : '') + n.text.to_s
147
+ }
148
+ end
137
149
  }
138
150
 
139
- attributes.add(name, values)
151
+ attributes.add(name, values.flatten)
140
152
  end
141
153
 
142
154
  attributes
@@ -316,11 +328,9 @@ module OneLogin
316
328
 
317
329
  # Validates that the SAML Response provided in the initialization is not empty,
318
330
  # also check that the setting and the IdP cert were also provided
319
- # @param soft [Boolean] soft Enable or Disable the soft mode (In order to raise exceptions when the response is invalid or not)
320
- # @return [Boolean] True if the required info is found, otherwise False if soft=True
321
- # @raise [ValidationError] if soft == false and validation fails
331
+ # @return [Boolean] True if the required info is found, false otherwise
322
332
  #
323
- def validate_response_state(soft = true)
333
+ def validate_response_state
324
334
  return append_error("Blank response") if response.nil? || response.empty?
325
335
 
326
336
  return append_error("No settings on response") if settings.nil?
@@ -504,7 +514,7 @@ module OneLogin
504
514
  return true if session_expires_at.nil?
505
515
 
506
516
  now = Time.now.utc
507
- unless session_expires_at > (now + allowed_clock_drift)
517
+ unless (session_expires_at + allowed_clock_drift) > now
508
518
  error_msg = "The attributes have expired, based on the SessionNotOnOrAfter of the AttributeStatement of this Response"
509
519
  return append_error(error_msg)
510
520
  end
@@ -513,12 +523,14 @@ module OneLogin
513
523
  end
514
524
 
515
525
  # Validates if exists valid SubjectConfirmation (If the response was initialized with the :allowed_clock_drift option,
516
- # timimg validation are relaxed by the allowed_clock_drift value)
526
+ # timimg validation are relaxed by the allowed_clock_drift value. If the response was initialized with the
527
+ # :skip_subject_confirmation option, this validation is skipped)
517
528
  # If fails, the error is added to the errors array
518
529
  # @return [Boolean] True if exists a valid SubjectConfirmation, otherwise False if soft=True
519
530
  # @raise [ValidationError] if soft == false and validation fails
520
531
  #
521
532
  def validate_subject_confirmation
533
+ return true if options[:skip_subject_confirmation]
522
534
  valid_subject_confirmation = false
523
535
 
524
536
  subject_confirmation_nodes = xpath_from_signed_assertion('/a:Subject/a:SubjectConfirmation')
@@ -560,6 +572,7 @@ module OneLogin
560
572
  #
561
573
  def validate_signature
562
574
  fingerprint = settings.get_fingerprint
575
+ idp_cert = settings.get_idp_cert
563
576
 
564
577
  # If the response contains the signature, and the assertion was encrypted, validate the original SAML Response
565
578
  # otherwise, review if the decrypted assertion contains a signature
@@ -571,7 +584,11 @@ module OneLogin
571
584
  )
572
585
  doc = (response_signed || decrypted_document.nil?) ? document : decrypted_document
573
586
 
574
- unless fingerprint && doc.validate_document(fingerprint, :fingerprint_alg => settings.idp_cert_fingerprint_algorithm)
587
+ opts = {}
588
+ opts[:fingerprint_alg] = settings.idp_cert_fingerprint_algorithm
589
+ opts[:cert] = idp_cert
590
+
591
+ unless fingerprint && doc.validate_document(fingerprint, @soft, opts)
575
592
  error_msg = "Invalid Signature on SAML Response"
576
593
  return append_error(error_msg)
577
594
  end
@@ -676,7 +693,7 @@ module OneLogin
676
693
  # @return [REXML::Document] The decrypted EncryptedAssertion element
677
694
  #
678
695
  def decrypt_assertion(encrypted_assertion_node)
679
- decrypt_element(encrypted_assertion_node, /(.*<\/(saml2*:|)Assertion>)/m)
696
+ decrypt_element(encrypted_assertion_node, /(.*<\/(\w+:)?Assertion>)/m)
680
697
  end
681
698
 
682
699
  # Decrypts an EncryptedID element
@@ -684,7 +701,7 @@ module OneLogin
684
701
  # @return [REXML::Document] The decrypted EncrypedtID element
685
702
  #
686
703
  def decrypt_nameid(encryptedid_node)
687
- decrypt_element(encryptedid_node, /(.*<\/(saml2*:|)NameID>)/m)
704
+ decrypt_element(encryptedid_node, /(.*<\/(\w+:)?NameID>)/m)
688
705
  end
689
706
 
690
707
  # Decrypt an element
@@ -23,7 +23,7 @@ module OneLogin
23
23
  # @return [Nokogiri::XML::Schema] Gets the schema object of the SAML 2.0 Protocol schema
24
24
  #
25
25
  def self.schema
26
- @schema ||= Mutex.new.synchronize do
26
+ Mutex.new.synchronize do
27
27
  Dir.chdir(File.expand_path("../../../schemas", __FILE__)) do
28
28
  ::Nokogiri::XML::Schema(File.read("saml-schema-protocol-2.0.xsd"))
29
29
  end
@@ -1,5 +1,5 @@
1
1
  module OneLogin
2
2
  module RubySaml
3
- VERSION = '1.0.0'
3
+ VERSION = '1.1.0'
4
4
  end
5
5
  end
@@ -199,77 +199,98 @@ module XMLSecurity
199
199
  "//ds:X509Certificate",
200
200
  { "ds"=>DSIG }
201
201
  )
202
- unless cert_element
203
- if soft
204
- return false
202
+
203
+ if cert_element
204
+ base64_cert = cert_element.text
205
+ cert_text = Base64.decode64(base64_cert)
206
+ cert = OpenSSL::X509::Certificate.new(cert_text)
207
+
208
+ if options[:fingerprint_alg]
209
+ fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(options[:fingerprint_alg]).new
205
210
  else
206
- raise OneLogin::RubySaml::ValidationError.new("Certificate element missing in response (ds:X509Certificate)")
211
+ fingerprint_alg = OpenSSL::Digest::SHA1.new
207
212
  end
208
- end
209
- base64_cert = cert_element.text
210
- cert_text = Base64.decode64(base64_cert)
211
- cert = OpenSSL::X509::Certificate.new(cert_text)
213
+ fingerprint = fingerprint_alg.hexdigest(cert.to_der)
212
214
 
213
- if options[:fingerprint_alg]
214
- fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(options[:fingerprint_alg]).new
215
+ # check cert matches registered idp cert
216
+ if fingerprint != idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/,"").downcase
217
+ @errors << "Fingerprint mismatch"
218
+ return soft ? false : (raise OneLogin::RubySaml::ValidationError.new("Fingerprint mismatch"))
219
+ end
215
220
  else
216
- fingerprint_alg = OpenSSL::Digest::SHA1.new
217
- end
218
- fingerprint = fingerprint_alg.hexdigest(cert.to_der)
219
-
220
- # check cert matches registered idp cert
221
- if fingerprint != idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/,"").downcase
222
- @errors << "Fingerprint mismatch"
223
- return soft ? false : (raise OneLogin::RubySaml::ValidationError.new("Fingerprint mismatch"))
221
+ if options[:cert]
222
+ base64_cert = Base64.encode64(options[:cert].to_pem)
223
+ else
224
+ if soft
225
+ return false
226
+ else
227
+ raise OneLogin::RubySaml::ValidationError.new("Certificate element missing in response (ds:X509Certificate) and not cert provided at settings")
228
+ end
229
+ end
224
230
  end
225
-
226
231
  validate_signature(base64_cert, soft)
227
232
  end
228
233
 
229
234
  def validate_signature(base64_cert, soft = true)
230
- # validate references
231
-
232
- # check for inclusive namespaces
233
- inclusive_namespaces = extract_inclusive_namespaces
234
235
 
235
236
  document = Nokogiri.parse(self.to_s) do |options|
236
237
  options = XMLSecurity::BaseDocument::NOKOGIRI_OPTIONS
237
238
  end
238
239
 
239
- # create a working copy so we don't modify the original
240
+ # create a rexml document
240
241
  @working_copy ||= REXML::Document.new(self.to_s).root
241
242
 
242
- # store and remove signature node
243
- @sig_element ||= begin
244
- element = REXML::XPath.first(
243
+ # get signature node
244
+ sig_element = REXML::XPath.first(
245
245
  @working_copy,
246
246
  "//ds:Signature",
247
247
  {"ds"=>DSIG}
248
- )
249
- element.remove
250
- end
248
+ )
251
249
 
252
- # verify signature
253
- signed_info_element = REXML::XPath.first(
254
- @sig_element,
255
- "//ds:SignedInfo",
250
+ # signature method
251
+ sig_alg_value = REXML::XPath.first(
252
+ sig_element,
253
+ "./ds:SignedInfo/ds:SignatureMethod",
256
254
  {"ds"=>DSIG}
257
255
  )
258
- noko_sig_element = document.at_xpath('//ds:Signature', 'ds' => DSIG)
259
- noko_signed_info_element = noko_sig_element.at_xpath('./ds:SignedInfo', 'ds' => DSIG)
256
+ signature_algorithm = algorithm(sig_alg_value)
257
+
258
+ # get signature
259
+ base64_signature = REXML::XPath.first(
260
+ sig_element,
261
+ "./ds:SignatureValue",
262
+ {"ds" => DSIG}
263
+ ).text
264
+ signature = Base64.decode64(base64_signature)
265
+
266
+ # canonicalization method
260
267
  canon_algorithm = canon_algorithm REXML::XPath.first(
261
- @sig_element,
262
- '//ds:CanonicalizationMethod',
268
+ sig_element,
269
+ './ds:SignedInfo/ds:CanonicalizationMethod',
263
270
  'ds' => DSIG
264
271
  )
272
+
273
+ noko_sig_element = document.at_xpath('//ds:Signature', 'ds' => DSIG)
274
+ noko_signed_info_element = noko_sig_element.at_xpath('./ds:SignedInfo', 'ds' => DSIG)
275
+
276
+ # Handle when no URI
277
+ noko_signed_info_reference_element_uri_attr = noko_signed_info_element.at_xpath('./ds:Reference', 'ds' => DSIG).attributes["URI"]
278
+ if (noko_signed_info_reference_element_uri_attr.value.empty?)
279
+ noko_signed_info_reference_element_uri_attr.value = "##{document.root.attribute('ID')}"
280
+ end
281
+
265
282
  canon_string = noko_signed_info_element.canonicalize(canon_algorithm)
266
283
  noko_sig_element.remove
267
284
 
285
+ # get inclusive namespaces
286
+ inclusive_namespaces = extract_inclusive_namespaces
287
+
268
288
  # check digests
269
- REXML::XPath.each(@sig_element, "//ds:Reference", {"ds"=>DSIG}) do |ref|
289
+ REXML::XPath.each(sig_element, "//ds:Reference", {"ds"=>DSIG}) do |ref|
270
290
  uri = ref.attributes.get_attribute("URI").value
271
291
 
272
- hashed_element = document.at_xpath("//*[@ID=$uri]", nil, { 'uri' => uri[1..-1] })
292
+ hashed_element = uri.empty? ? document : document.at_xpath("//*[@ID=$uri]", nil, { 'uri' => uri[1..-1] })
293
+ # hashed_element = document.at_xpath("//*[@ID=$uri]", nil, { 'uri' => uri[1..-1] })
273
294
  canon_algorithm = canon_algorithm REXML::XPath.first(
274
295
  ref,
275
296
  '//ds:CanonicalizationMethod',
@@ -296,26 +317,11 @@ module XMLSecurity
296
317
  end
297
318
  end
298
319
 
299
- base64_signature = REXML::XPath.first(
300
- @sig_element,
301
- "//ds:SignatureValue",
302
- {"ds" => DSIG}
303
- ).text
304
-
305
- signature = Base64.decode64(base64_signature)
306
-
307
320
  # get certificate object
308
321
  cert_text = Base64.decode64(base64_cert)
309
322
  cert = OpenSSL::X509::Certificate.new(cert_text)
310
323
 
311
- # signature method
312
- sig_alg_value = REXML::XPath.first(
313
- signed_info_element,
314
- "//ds:SignatureMethod",
315
- {"ds"=>DSIG}
316
- )
317
- signature_algorithm = algorithm(sig_alg_value)
318
-
324
+ # verify signature
319
325
  unless cert.public_key.verify(signature_algorithm.new, signature, canon_string)
320
326
  @errors << "Key validation error"
321
327
  return soft ? false : (raise OneLogin::RubySaml::ValidationError.new("Key validation error"))
@@ -336,7 +342,11 @@ module XMLSecurity
336
342
  "//ds:Signature/ds:SignedInfo/ds:Reference",
337
343
  {"ds"=>DSIG}
338
344
  )
339
- self.signed_element_id = reference_element.attribute("URI").value[1..-1] unless reference_element.nil?
345
+
346
+ return nil if reference_element.nil?
347
+
348
+ sei = reference_element.attribute("URI").value[1..-1]
349
+ sei.nil? ? self.root.attribute("ID") : sei
340
350
  end
341
351
 
342
352
  def extract_inclusive_namespaces
@@ -349,7 +359,7 @@ module XMLSecurity
349
359
  prefix_list = element.attributes.get_attribute("PrefixList").value
350
360
  prefix_list.split(" ")
351
361
  else
352
- []
362
+ nil
353
363
  end
354
364
  end
355
365
 
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.license = 'MIT'
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
16
- "README.md"
16
+ "README.md"
17
17
  ]
18
18
  s.files = `git ls-files`.split("\n")
19
19
  s.homepage = %q{http://github.com/onelogin/ruby-saml}
@@ -30,7 +30,12 @@ Gem::Specification.new do |s|
30
30
  # Because runtime dependencies are determined at build time, we cannot make
31
31
  # Nokogiri's version dependent on the Ruby version, even though we would
32
32
  # have liked to constrain Ruby 1.8.7 to install only the 1.5.x versions.
33
- s.add_runtime_dependency('nokogiri', '>= 1.5.10')
33
+ if defined?(JRUBY_VERSION)
34
+ s.add_runtime_dependency('nokogiri', '>= 1.6.0')
35
+ s.add_runtime_dependency('jruby-openssl', '>= 0.9.8')
36
+ else
37
+ s.add_runtime_dependency('nokogiri', '>= 1.5.10')
38
+ end
34
39
 
35
40
  s.add_development_dependency('minitest', '~> 5.5')
36
41
  s.add_development_dependency('mocha', '~> 0.14')
@@ -40,7 +45,10 @@ Gem::Specification.new do |s|
40
45
  s.add_development_dependency('systemu', '~> 2')
41
46
  s.add_development_dependency('timecop', '<= 0.6.0')
42
47
 
43
- if RUBY_VERSION < '1.9'
48
+ if defined?(JRUBY_VERSION)
49
+ # All recent versions of JRuby play well with pry
50
+ s.add_development_dependency('pry')
51
+ elsif RUBY_VERSION < '1.9'
44
52
  # 1.8.7
45
53
  s.add_development_dependency('ruby-debug', '~> 0.10.4')
46
54
  elsif RUBY_VERSION < '2.0'
@@ -9,11 +9,14 @@ class RubySamlTest < Minitest::Test
9
9
  let(:settings) { OneLogin::RubySaml::Settings.new }
10
10
  let(:response) { OneLogin::RubySaml::Response.new(response_document_without_recipient) }
11
11
  let(:response_without_attributes) { OneLogin::RubySaml::Response.new(response_document_without_attributes) }
12
+ let(:response_without_reference_uri) { OneLogin::RubySaml::Response.new(response_document_without_reference_uri) }
12
13
  let(:response_with_signed_assertion) { OneLogin::RubySaml::Response.new(response_document_with_signed_assertion) }
14
+ let(:response_with_ds_namespace_at_the_root) { OneLogin::RubySaml::Response.new(response_document_with_ds_namespace_at_the_root)}
13
15
  let(:response_unsigned) { OneLogin::RubySaml::Response.new(response_document_unsigned) }
14
16
  let(:response_wrapped) { OneLogin::RubySaml::Response.new(response_document_wrapped) }
15
17
  let(:response_multiple_attr_values) { OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values)) }
16
18
  let(:response_valid_signed) { OneLogin::RubySaml::Response.new(response_document_valid_signed) }
19
+ let(:response_valid_signed_without_x509certificate) { OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate) }
17
20
  let(:response_no_id) { OneLogin::RubySaml::Response.new(read_invalid_response("no_id.xml.base64")) }
18
21
  let(:response_no_version) { OneLogin::RubySaml::Response.new(read_invalid_response("no_saml2.xml.base64")) }
19
22
  let(:response_multi_assertion) { OneLogin::RubySaml::Response.new(read_invalid_response("multiple_assertions.xml.base64")) }
@@ -55,7 +58,7 @@ class RubySamlTest < Minitest::Test
55
58
 
56
59
  describe "Prevent XEE attack" do
57
60
  before do
58
- @response = OneLogin::RubySaml::Response.new(fixture(:attackxee))
61
+ @response = OneLogin::RubySaml::Response.new(fixture(:attackxee))
59
62
  end
60
63
 
61
64
  it "false when evil attack vector is present, soft = true" do
@@ -384,6 +387,15 @@ class RubySamlTest < Minitest::Test
384
387
  response_no_version.is_valid?
385
388
  assert_includes response_no_version.errors, "Unsupported SAML version"
386
389
  end
390
+
391
+ it "return true when a nil URI is given in the ds:Reference" do
392
+
393
+ response_without_reference_uri.stubs(:conditions).returns(nil)
394
+ response_without_reference_uri.settings = settings
395
+ response_without_reference_uri.settings.idp_cert_fingerprint = "19:4D:97:E4:D8:C9:C8:CF:A4:B7:21:E5:EE:49:7F:D9:66:0E:52:13"
396
+ assert response_without_reference_uri.is_valid?
397
+ assert_empty response_without_reference_uri.errors
398
+ end
387
399
  end
388
400
  end
389
401
 
@@ -409,7 +421,7 @@ class RubySamlTest < Minitest::Test
409
421
  assert response_valid_signed.send(:validate_issuer)
410
422
 
411
423
  response_valid_signed.settings.idp_entity_id = 'https://app.onelogin.com/saml2'
412
- assert response_valid_signed.send(:validate_issuer)
424
+ assert response_valid_signed.send(:validate_issuer)
413
425
  end
414
426
 
415
427
  it "return false when the issuer of the Message does not match the IdP entityId" do
@@ -491,7 +503,7 @@ class RubySamlTest < Minitest::Test
491
503
  response = OneLogin::RubySaml::Response.new(response_document_valid_signed, :settings => settings, :matches_request_id => "_fc4a34b0-7efb-012e-caae-782bcb13bb38")
492
504
  assert response.send(:validate_in_response_to)
493
505
  assert_empty response.errors
494
- end
506
+ end
495
507
 
496
508
  it "return true when no Request ID is provided for checking" do
497
509
  response = OneLogin::RubySaml::Response.new(response_document_valid_signed, :settings => settings)
@@ -606,6 +618,27 @@ class RubySamlTest < Minitest::Test
606
618
  assert !response_invalid_subjectconfirmation_noa.send(:validate_subject_confirmation)
607
619
  assert_includes response_invalid_subjectconfirmation_noa.errors, "A valid SubjectConfirmation was not found on this Response"
608
620
  end
621
+
622
+ it "return true when the skip_subject_confirmation option is passed and the subject confirmation is valid" do
623
+ opts = {}
624
+ opts[:skip_subject_confirmation] = true
625
+ response_with_skip = OneLogin::RubySaml::Response.new(response_document_valid_signed, opts)
626
+ response_with_skip.settings = settings
627
+ response_with_skip.settings.assertion_consumer_service_url = 'recipient'
628
+ Time.expects(:now).times(0) # ensures the test isn't run and thus Time.now.utc is never called within the test
629
+ assert response_with_skip.send(:validate_subject_confirmation)
630
+ assert_empty response_with_skip.errors
631
+ end
632
+
633
+ it "return true when the skip_subject_confirmation option is passed and the response has an invalid subject confirmation" do
634
+ opts = {}
635
+ opts[:skip_subject_confirmation] = true
636
+ response_with_skip = OneLogin::RubySaml::Response.new(read_invalid_response("invalid_subjectconfirmation_noa.xml.base64"), opts)
637
+ response_with_skip.settings = settings
638
+ Time.expects(:now).times(0) # ensures the test isn't run and thus Time.now.utc is never called within the test
639
+ assert response_with_skip.send(:validate_subject_confirmation)
640
+ assert_empty response_with_skip.errors
641
+ end
609
642
  end
610
643
 
611
644
  describe "#validate_session_expiration" do
@@ -620,6 +653,18 @@ class RubySamlTest < Minitest::Test
620
653
  assert !response.send(:validate_session_expiration)
621
654
  assert_includes response.errors, "The attributes have expired, based on the SessionNotOnOrAfter of the AttributeStatement of this Response"
622
655
  end
656
+
657
+ it "returns true when the session has expired, but is still within the allowed_clock_drift" do
658
+ drift = (Time.now - Time.parse("2010-11-19T21:57:37Z")) * 60 # seconds ago that this assertion expired
659
+ drift += 10 # add a buffer of 10 seconds to make sure the test passes
660
+ opts = {}
661
+ opts[:allowed_clock_drift] = drift
662
+
663
+ response_with_drift = OneLogin::RubySaml::Response.new(response_document_without_recipient, opts)
664
+ response_with_drift.settings = settings
665
+ assert response_with_drift.send(:validate_session_expiration)
666
+ assert_empty response_with_drift.errors
667
+ end
623
668
  end
624
669
 
625
670
  describe "#validate_signature" do
@@ -630,6 +675,13 @@ class RubySamlTest < Minitest::Test
630
675
  assert_empty response_valid_signed.errors
631
676
  end
632
677
 
678
+ it "return true when the signature is valid and ds namespace is at the root" do
679
+ settings.idp_cert_fingerprint = '5614657ab692b960480389723a36446a5fe1f7ec'
680
+ response_with_ds_namespace_at_the_root.settings = settings
681
+ assert response_with_ds_namespace_at_the_root.send(:validate_signature)
682
+ assert_empty response_with_ds_namespace_at_the_root.errors
683
+ end
684
+
633
685
  it "return false when no fingerprint" do
634
686
  settings.idp_cert_fingerprint = nil
635
687
  settings.idp_cert = nil
@@ -644,6 +696,30 @@ class RubySamlTest < Minitest::Test
644
696
  assert !response.send(:validate_signature)
645
697
  assert_includes response.errors, "Invalid Signature on SAML Response"
646
698
  end
699
+
700
+ it "return false when no X509Certificate and not cert provided at settings" do
701
+ settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
702
+ settings.idp_cert = nil
703
+ response_valid_signed_without_x509certificate.settings = settings
704
+ assert !response_valid_signed_without_x509certificate.send(:validate_signature)
705
+ assert_includes response_valid_signed_without_x509certificate.errors, "Invalid Signature on SAML Response"
706
+ end
707
+
708
+ it "return false when no X509Certificate and the cert provided at settings mismatches" do
709
+ settings.idp_cert_fingerprint = nil
710
+ settings.idp_cert = signature_1
711
+ response_valid_signed_without_x509certificate.settings = settings
712
+ assert !response_valid_signed_without_x509certificate.send(:validate_signature)
713
+ assert_includes response_valid_signed_without_x509certificate.errors, "Invalid Signature on SAML Response"
714
+ end
715
+
716
+ it "return true when no X509Certificate and the cert provided at settings matches" do
717
+ settings.idp_cert_fingerprint = nil
718
+ settings.idp_cert = ruby_saml_cert_text
719
+ response_valid_signed_without_x509certificate.settings = settings
720
+ assert response_valid_signed_without_x509certificate.send(:validate_signature)
721
+ assert_empty response_valid_signed_without_x509certificate.errors
722
+ end
647
723
  end
648
724
 
649
725
  describe "#nameid" do
@@ -888,7 +964,7 @@ class RubySamlTest < Minitest::Test
888
964
  it 'is not possible when encryptID inside the assertion but no private key' do
889
965
  response_encrypted_nameid.settings = settings
890
966
  assert_raises(OneLogin::RubySaml::ValidationError, "An EncryptedID found and no SP private key found on the settings to decrypt it") do
891
- assert_equal "test@onelogin.com", response_encrypted_nameid.nameid
967
+ assert_equal "test@onelogin.com", response_encrypted_nameid.nameid
892
968
  end
893
969
  end
894
970
 
@@ -1007,7 +1083,7 @@ class RubySamlTest < Minitest::Test
1007
1083
  describe "check right settings" do
1008
1084
 
1009
1085
  it "is not possible to decrypt the assertion if no private key" do
1010
- response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
1086
+ response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
1011
1087
 
1012
1088
  encrypted_assertion_node = REXML::XPath.first(
1013
1089
  response.document,
@@ -1023,7 +1099,7 @@ class RubySamlTest < Minitest::Test
1023
1099
  end
1024
1100
 
1025
1101
  it "is possible to decrypt the assertion if private key" do
1026
- response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
1102
+ response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
1027
1103
 
1028
1104
  encrypted_assertion_node = REXML::XPath.first(
1029
1105
  response.document,
@@ -1090,5 +1166,27 @@ class RubySamlTest < Minitest::Test
1090
1166
  assert_equal "_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7", response.nameid
1091
1167
  end
1092
1168
  end
1169
+
1170
+ end
1171
+ describe "test qualified name id in attributes" do
1172
+
1173
+ it "parsed the nameid" do
1174
+ response = OneLogin::RubySaml::Response.new(read_response("signed_nameid_in_atts.xml"), :settings => settings)
1175
+ response.settings.idp_cert_fingerprint = 'c51985d947f1be57082025050846eb27f6cab783'
1176
+ assert_empty response.errors
1177
+ assert_equal "test", response.attributes[:uid]
1178
+ assert_equal "http://idp.example.com/metadata.php/ZdrjpwEdw22vKoxWAbZB78/gQ7s=", response.attributes.single('urn:oid:1.3.6.1.4.1.5923.1.1.1.10')
1179
+ end
1180
+ end
1181
+
1182
+ describe "test unqualified name id in attributes" do
1183
+
1184
+ it "parsed the nameid" do
1185
+ response = OneLogin::RubySaml::Response.new(read_response("signed_unqual_nameid_in_atts.xml"), :settings => settings)
1186
+ response.settings.idp_cert_fingerprint = 'c51985d947f1be57082025050846eb27f6cab783'
1187
+ assert_empty response.errors
1188
+ assert_equal "test", response.attributes[:uid]
1189
+ assert_equal "ZdrjpwEdw22vKoxWAbZB78/gQ7s=", response.attributes.single('urn:oid:1.3.6.1.4.1.5923.1.1.1.10')
1190
+ end
1093
1191
  end
1094
1192
  end
@@ -0,0 +1 @@
1
+ PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiDQp4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9Il84ZThkYzVmNjlhOThjYzRjMWZmMzQyN2U1Y2UzNDYwNmZkNjcyZjkxZTYiIFZlcnNpb249IjIuMCIgSXNzdWVJbnN0YW50PSIyMDE0LTA3LTE3VDAxOjAxOjQ4WiIgRGVzdGluYXRpb249Imh0dHA6Ly9zcC5leGFtcGxlLmNvbS9kZW1vMS9pbmRleC5waHA/YWNzIiBJblJlc3BvbnNlVG89Ik9ORUxPR0lOXzRmZWUzYjA0NjM5NWM0ZTc1MTAxMWU5N2Y4OTAwYjUyNzNkNTY2ODUiPg0KICA8c2FtbDpJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS9tZXRhZGF0YS5waHA8L3NhbWw6SXNzdWVyPg0KICA8c2FtbHA6U3RhdHVzPg0KICAgIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz4NCiAgPC9zYW1scDpTdGF0dXM+DQogIDxzYW1sOkFzc2VydGlvbiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIElEPSJwZng2YzViMTVjYy02YzY4LTljMWYtY2QzNy05ZTFmYTFkMmU3YTAiIFZlcnNpb249IjIuMCIgSXNzdWVJbnN0YW50PSIyMDE0LTA3LTE3VDAxOjAxOjQ4WiI+DQogICAgPHNhbWw6SXNzdWVyPmh0dHA6Ly9pZHAuZXhhbXBsZS5jb20vbWV0YWRhdGEucGhwPC9zYW1sOklzc3Vlcj48ZHM6U2lnbmF0dXJlPg0KICA8ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPg0KICAgIDxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjcnNhLXNoYTEiLz4NCiAgPGRzOlJlZmVyZW5jZSBVUkk9IiNwZng2YzViMTVjYy02YzY4LTljMWYtY2QzNy05ZTFmYTFkMmU3YTAiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIi8+PGRzOkRpZ2VzdFZhbHVlPmlHdENJcGpyZ09Hc2FDY0lFOEtwSWEzVzZnVT08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+T0RIU2tzUkl1ZEc3b2s0KzRUZitPRnA0UFJ4Ukc3d3BERGdyVDZwQk5ZbUFKNUN2dFk5UlczRldHYlJtZ2NoSjdhYW9sQ3ViekQ5Qkk4Y01nb3V6ZGErdjcrZ1k4THloVUNmV2RSd0gvSzZlVmYvZUtldjk3aUQ1YVA1TTU1MCtCZ0NVaHVWNFg0MlpUbFhkdjBVKzRDQ1VYWnFuLzRjczBxNXhkeTBoM0JzPTwvZHM6U2lnbmF0dXJlVmFsdWU+DQo8ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlDYWpDQ0FkT2dBd0lCQWdJQkFEQU5CZ2txaGtpRzl3MEJBUTBGQURCU01Rc3dDUVlEVlFRR0V3SjFjekVUTUJFR0ExVUVDQXdLUTJGc2FXWnZjbTVwWVRFVk1CTUdBMVVFQ2d3TVQyNWxiRzluYVc0Z1NXNWpNUmN3RlFZRFZRUUREQTV6Y0M1bGVHRnRjR3hsTG1OdmJUQWVGdzB4TkRBM01UY3hOREV5TlRaYUZ3MHhOVEEzTVRjeE5ERXlOVFphTUZJeEN6QUpCZ05WQkFZVEFuVnpNUk13RVFZRFZRUUlEQXBEWVd4cFptOXlibWxoTVJVd0V3WURWUVFLREF4UGJtVnNiMmRwYmlCSmJtTXhGekFWQmdOVkJBTU1Ebk53TG1WNFlXMXdiR1V1WTI5dE1JR2ZNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0R05BRENCaVFLQmdRRFp4K09ONElVb0lXeGd1a1RiMXRPaVgzYk1ZellRaXdXUFVOTXArRnE4MnhvTm9nc28yYnlrWkcweWlKbTVvOHp2L3NkNnBHb3VheU1na3gvMkZTT2RjMzZUMGpHYkNIdVJTYnRpYTBQRXpOSVJ0bVZpTXJ0M0Flb1dCaWRSWG1ac3hDTkx3Z0lWNmRuMldwdUU1QXowYkhncFpuUXhUS0ZlazBCTUtVL2Q4d0lEQVFBQm8xQXdUakFkQmdOVkhRNEVGZ1FVR0h4WXFaWXlYN2NUeEtWT0RWZ1p3U1RkQ253d0h3WURWUjBqQkJnd0ZvQVVHSHhZcVpZeVg3Y1R4S1ZPRFZnWndTVGRDbnd3REFZRFZSMFRCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUTBGQUFPQmdRQnlGT2wraE1GSUNiZDNESmZucDJSZ2QvZHF0dHNaRy90eWhJTFd2RXJiaW8vREVlOThtWHBvd2hUa0MwNEVOcHJPeVhpN1piVXFpaWNGODl1QUd5dDFvcWdUVUNEMVZzTGFocUljbXJ6Z3VtTnlUd0xHV28xN1dEQWExL3VzRGhldFdBTWhnekYvQ25mNWVrMG5LMDBtMFlaR3ljNEx6Z0QwQ1JPTUFTVFdOZz09PC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+DQogICAgPHNhbWw6U3ViamVjdD4NCiAgICAgIDxzYW1sOk5hbWVJRCBTUE5hbWVRdWFsaWZpZXI9Imh0dHA6Ly9zcC5leGFtcGxlLmNvbS9kZW1vMS9tZXRhZGF0YS5waHAiIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6dHJhbnNpZW50Ij5fY2UzZDI5NDhiNGNmMjAxNDZkZWUwYTBiM2RkNmY2OWI2Y2Y4NmY2MmQ3PC9zYW1sOk5hbWVJRD4NCiAgICAgIDxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj4NCiAgICAgICAgPHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgTm90T25PckFmdGVyPSIyMDI0LTAxLTE4VDA2OjIxOjQ4WiIgUmVjaXBpZW50PSJodHRwOi8vc3AuZXhhbXBsZS5jb20vZGVtbzEvaW5kZXgucGhwP2FjcyIgSW5SZXNwb25zZVRvPSJPTkVMT0dJTl80ZmVlM2IwNDYzOTVjNGU3NTEwMTFlOTdmODkwMGI1MjczZDU2Njg1Ii8+DQogICAgICA8L3NhbWw6U3ViamVjdENvbmZpcm1hdGlvbj4NCiAgICA8L3NhbWw6U3ViamVjdD4NCiAgICA8c2FtbDpDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAxNC0wNy0xN1QwMTowMToxOFoiIE5vdE9uT3JBZnRlcj0iMjAyNC0wMS0xOFQwNjoyMTo0OFoiPg0KICAgICAgPHNhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj4NCiAgICAgICAgPHNhbWw6QXVkaWVuY2U+aHR0cDovL3NwLmV4YW1wbGUuY29tL2RlbW8xL21ldGFkYXRhLnBocDwvc2FtbDpBdWRpZW5jZT4NCiAgICAgIDwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgIDwvc2FtbDpDb25kaXRpb25zPg0KICAgIDxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNC0wNy0xN1QwMTowMTo0OFoiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwMjQtMDctMTdUMDk6MDE6NDhaIiBTZXNzaW9uSW5kZXg9Il9iZTk5NjdhYmQ5MDRkZGNhZTNjMGViNDE4OWFkYmUzZjcxZTMyN2NmOTMiPg0KICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Pg0KICAgICAgICA8c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj4NCiAgICAgIDwvc2FtbDpBdXRobkNvbnRleHQ+DQogICAgPC9zYW1sOkF1dGhuU3RhdGVtZW50Pg0KICAgIDxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICAgIDxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJ1aWQiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6YmFzaWMiPg0KICAgICAgICA8c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj50ZXN0PC9zYW1sOkF0dHJpYnV0ZVZhbHVlPg0KICAgICAgPC9zYW1sOkF0dHJpYnV0ZT4NCiAgICAgIDxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj4NCiAgICAgICAgPHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+dGVzdEBleGFtcGxlLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvc2FtbDpBdHRyaWJ1dGU+DQogICAgICA8c2FtbDpBdHRyaWJ1dGUgTmFtZT0iZWR1UGVyc29uQWZmaWxpYXRpb24iIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6YmFzaWMiPg0KICAgICAgICA8c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj51c2Vyczwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT4NCiAgICAgICAgPHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+ZXhhbXBsZXJvbGUxPC9zYW1sOkF0dHJpYnV0ZVZhbHVlPg0KICAgICAgPC9zYW1sOkF0dHJpYnV0ZT4NCiAgICA8L3NhbWw6QXR0cmlidXRlU3RhdGVtZW50Pg0KICA8L3NhbWw6QXNzZXJ0aW9uPg0KPC9zYW1scDpSZXNwb25zZT4=
@@ -0,0 +1 @@
1
+ PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgSUQ9InBmeGQ1OTQzNDdkLTQ5NWYtYjhkMS0wZWUyLTQxY2ZkYTE0ZGQzNSIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTUtMDEtMDJUMjI6NDg6NDhaIiBEZXN0aW5hdGlvbj0iaHR0cDovL2xvY2FsaG9zdDo5MDAxL3YxL3VzZXJzL2F1dGhvcml6ZS9zYW1sIiBDb25zZW50PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y29uc2VudDp1bnNwZWNpZmllZCIgSW5SZXNwb25zZVRvPSJfZWQ5MTVhNDAtNzRmYi0wMTMyLTViMTYtNDhlMGViMTRhMWM3Ij4NCiAgPElzc3VlciB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI+aHR0cDovL2V4YW1wbGUuY29tPC9Jc3N1ZXI+PGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+DQogIDxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+DQogICAgPGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNyc2Etc2hhMSIvPg0KICA8ZHM6UmVmZXJlbmNlIFVSST0iIj48ZHM6VHJhbnNmb3Jtcz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjc2hhMSIvPjxkczpEaWdlc3RWYWx1ZT5qQ2dlWENQREZsd2pUZ3FnUHAwbVUyVHF3OWc9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8+PGRzOlNpZ25hdHVyZVZhbHVlPkRmdXByMTh3UityRGFndENQRWZRbFNHSHp3NE5kZlBIWjRIc3pGZTFKUENKWGpmYnlFTTFmZytqemdHYk1NdDZYemdDWGNLSk03RS9DUFNURGt2TWUzRFVKbEh1NERodURPQXovRHN5b0J3V3VWK1JmM1dpTmNGNFhDYzl3QlF6dm4vYXREN3pXNnh3TzdOL2hrQVpKcWZ2SmRkbnBNTUhLR1hxRy9aSFpBdz08L2RzOlNpZ25hdHVyZVZhbHVlPg0KPGRzOktleUluZm8+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJQ3FEQ0NBaEdnQXdJQkFnSUJBREFOQmdrcWhraUc5dzBCQVEwRkFEQnhNUXN3Q1FZRFZRUUdFd0oxY3pFVE1CRUdBMVVFQ0F3S1YyRnphR2x1WjNSdmJqRWlNQ0FHQTFVRUNnd1pSbXhoZENCWGIzSnNaQ0JMYm05M2JHVmtaMlVzSUVsdVl6RWNNQm9HQTFVRUF3d1RiR1ZoY200dVpteGhkSGR2Y214a0xtTnZiVEVMTUFrR0ExVUVCd3dDUkVNd0hoY05NVFV3TnpBNE1EazFPVEF6V2hjTk1qVXdOekExTURrMU9UQXpXakJ4TVFzd0NRWURWUVFHRXdKMWN6RVRNQkVHQTFVRUNBd0tWMkZ6YUdsdVozUnZiakVpTUNBR0ExVUVDZ3daUm14aGRDQlhiM0pzWkNCTGJtOTNiR1ZrWjJVc0lFbHVZekVjTUJvR0ExVUVBd3dUYkdWaGNtNHVabXhoZEhkdmNteGtMbU52YlRFTE1Ba0dBMVVFQnd3Q1JFTXdnWjh3RFFZSktvWklodmNOQVFFQkJRQURnWTBBTUlHSkFvR0JBTVBEd3NsNW82eDJRb3VOaTEvRTdJVXFSWWoyWW9jSlJGc3VFR1RldnlVKzJhRkNhQk5WL3R0NnNBYk05V1N1dEx1cWpFL2hmYm5sRWNaMDMrZ24wQ29MbDZZbXdiS0tlUnBrSXplVmhveUoxWVlNUUVBVmhMcmR5OFBvd3U4VUNaMFBiQXorbjlka2lSek01cENDTzc3K2d5Y0ZUQkZLSEFBOXFJcFVaWmtQQWdNQkFBR2pVREJPTUIwR0ExVWREZ1FXQkJRSFU1OGl1R3hGbFp1ckJVSndvbGFsSnIrRlJ6QWZCZ05WSFNNRUdEQVdnQlFIVTU4aXVHeEZsWnVyQlVKd29sYWxKcitGUnpBTUJnTlZIUk1FQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCRFFVQUE0R0JBQzZpSGZNbWQraE1TUnpma29zaTNDK3d2cUhDTEVVc2czSEZwa1ptNWp4bVREbEY1cU8rQnQwbjB4bWZvcVdCekJNbE5DOFRzR3JhZmhKM3p1OEdORjBMZW8xMXJmYzFHTUdCdnI1SG9aM1dBQXltbkJFREFBb3N4TjZXWlJtajF4YWdhMTMrNnBXZkdCKysyblB3Y1pXUC84ZGtQY1JvZ2V2VjB4MHA1Njg2PC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+DQogIDxzYW1scDpTdGF0dXM+DQogICAgPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPg0KICA8L3NhbWxwOlN0YXR1cz4NCg0KICA8QXNzZXJ0aW9uIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iXzcwMGFjMzIwLTc0ZmYtMDEzMi01YjE0LTQ4ZTBlYjE0YTFjNyIgSXNzdWVJbnN0YW50PSIyMDE1LTAxLTAyVDIyOjQ4OjQ4WiIgVmVyc2lvbj0iMi4wIj4NCiAgICA8SXNzdWVyPmh0dHA6Ly9leGFtcGxlLmNvbTwvSXNzdWVyPg0KICAgIDxTdWJqZWN0Pg0KICAgICAgPE5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI+c2FtbEB1c2VyLmNvbTwvTmFtZUlEPg0KICAgICAgPFN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj4NCiAgICAgICAgPFN1YmplY3RDb25maXJtYXRpb25EYXRhIEluUmVzcG9uc2VUbz0iX2VkOTE1YTQwLTc0ZmItMDEzMi01YjE2LTQ4ZTBlYjE0YTFjNyIgTm90T25PckFmdGVyPSIyMDM4LTAxLTAyVDIyOjUxOjQ4WiIgUmVjaXBpZW50PSJodHRwOi8vbG9jYWxob3N0OjkwMDEvdjEvdXNlcnMvYXV0aG9yaXplL3NhbWwiLz4NCiAgICAgIDwvU3ViamVjdENvbmZpcm1hdGlvbj4NCiAgICA8L1N1YmplY3Q+DQogICAgPENvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDE1LTAxLTAyVDIyOjQ4OjQzWiIgTm90T25PckFmdGVyPSIyMDM4LTAxLTAyVDIzOjQ4OjQ4WiI+DQogICAgICA8QXVkaWVuY2VSZXN0cmljdGlvbj4NCiAgICAgICAgPEF1ZGllbmNlPmh0dHA6Ly9sb2NhbGhvc3Q6OTAwMS88L0F1ZGllbmNlPg0KICAgICAgICA8QXVkaWVuY2U+ZmxhdF93b3JsZDwvQXVkaWVuY2U+DQogICAgICA8L0F1ZGllbmNlUmVzdHJpY3Rpb24+DQogICAgPC9Db25kaXRpb25zPg0KICAgIDxBdHRyaWJ1dGVTdGF0ZW1lbnQ+DQogICAgICA8QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI+DQogICAgICAgIDxBdHRyaWJ1dGVWYWx1ZT5zYW1sQHVzZXIuY29tPC9BdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvQXR0cmlidXRlPg0KICAgIDwvQXR0cmlidXRlU3RhdGVtZW50Pg0KICAgIDxBdXRoblN0YXRlbWVudCBBdXRobkluc3RhbnQ9IjIwMTUtMDEtMDJUMjI6NDg6NDhaIiBTZXNzaW9uSW5kZXg9Il83MDBhYzMyMC03NGZmLTAxMzItNWIxNC00OGUwZWIxNGExYzciPg0KICAgICAgPEF1dGhuQ29udGV4dD4NCiAgICAgICAgPEF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpmZWRlcmF0aW9uOmF1dGhlbnRpY2F0aW9uOndpbmRvd3M8L0F1dGhuQ29udGV4dENsYXNzUmVmPg0KICAgICAgPC9BdXRobkNvbnRleHQ+DQogICAgPC9BdXRoblN0YXRlbWVudD4NCiAgPC9Bc3NlcnRpb24+DQo8L3NhbWxwOlJlc3BvbnNlPg==
@@ -0,0 +1,47 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="pfx3437f097-cd95-f187-4501-0bce24d4d6f8" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685">
3
+ <saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
4
+ <ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
5
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
6
+ <ds:Reference URI="#pfx3437f097-cd95-f187-4501-0bce24d4d6f8"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>7IMOicPUD8hBuAv8HeVDrUErclY=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>jPBUr/iVsSXvMeT6PhQxSTbi3j6M34OQiyAKLPyPQWypX0uJ04UbC2J4v1DqFqC3OJYyepQ6OBocSMH4r+uqv4hdoWeaj1Ieeo4HRB5UFTxhR4TV8tTPpEZjGA2vXz74BjtCi6PMWVe/28/TejkAosHfe62WktcznTvfWKePlFA=</ds:SignatureValue>
7
+ <ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICGzCCAYQCCQCNNcQXom32VDANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzELMAkGA1UECBMCSU4xFTATBgNVBAcTDEluZGlhbmFwb2xpczERMA8GA1UEChMIT25lTG9naW4xDDAKBgNVBAsTA0VuZzAeFw0xNDA0MjMxODQxMDFaFw0xNTA0MjMxODQxMDFaMFIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTjEVMBMGA1UEBxMMSW5kaWFuYXBvbGlzMREwDwYDVQQKEwhPbmVMb2dpbjEMMAoGA1UECxMDRW5nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo6m+QZvYQ/xL0ElLgupK1QDcYL4f5PckwsNgS9pUvV7fzTqCHk8ThLxTk42MQ2McJsOeUJVP728KhymjFCqxgP4VuwRk9rpAl0+mhy6MPdyjyA6G14jrDWS65ysLchK4t/vwpEDz0SQlEoG1kMzllSm7zZS3XregA7DjNaUYQqwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBALM2vGCiQ/vm+a6v40+VX2zdqHA2Q/1vF1ibQzJ54MJCOVWvs+vQXfZFhdm0OPM2IrDU7oqvKPqP6xOAeJK6H0yP7M4YL3fatSvIYmmfyXC9kt3Svz/NyrHzPhUnJ0ye/sUSXxnzQxwcm/9PwAqrQaA3QpQkH57ybF/OoryPe+2h</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>
8
+ <samlp:Status>
9
+ <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
10
+ </samlp:Status>
11
+ <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_d71a3a8e9fcc45c9e9d248ef7049393fc8f04e5f75" Version="2.0" IssueInstant="2014-07-17T01:01:48Z">
12
+ <saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
13
+ <saml:Subject>
14
+ <saml:NameID SPNameQualifier="http://sp.example.com/demo1/metadata.php" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7</saml:NameID>
15
+ <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
16
+ <saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"/>
17
+ </saml:SubjectConfirmation>
18
+ </saml:Subject>
19
+ <saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z">
20
+ <saml:AudienceRestriction>
21
+ <saml:Audience>http://sp.example.com/demo1/metadata.php</saml:Audience>
22
+ </saml:AudienceRestriction>
23
+ </saml:Conditions>
24
+ <saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionNotOnOrAfter="2024-07-17T09:01:48Z" SessionIndex="_be9967abd904ddcae3c0eb4189adbe3f71e327cf93">
25
+ <saml:AuthnContext>
26
+ <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
27
+ </saml:AuthnContext>
28
+ </saml:AuthnStatement>
29
+ <saml:AttributeStatement>
30
+ <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
31
+ <saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
32
+ </saml:Attribute>
33
+ <saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
34
+ <saml:AttributeValue xsi:type="xs:string">test@example.com</saml:AttributeValue>
35
+ </saml:Attribute>
36
+ <saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
37
+ <saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
38
+ <saml:AttributeValue xsi:type="xs:string">examplerole1</saml:AttributeValue>
39
+ </saml:Attribute>
40
+ <saml:Attribute FriendlyName="eduPersonTargetedID" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
41
+ <saml:AttributeValue>
42
+ <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="http://idp.example.com/metadata.php" SPNameQualifier="http://sp.example.com/demo1/metadata.php">ZdrjpwEdw22vKoxWAbZB78/gQ7s=</saml:NameID>
43
+ </saml:AttributeValue>
44
+ </saml:Attribute>
45
+ </saml:AttributeStatement>
46
+ </saml:Assertion>
47
+ </samlp:Response>
@@ -0,0 +1,47 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="pfx852f7331-dd1c-95c3-9cbe-0ab1ebf9c538" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685">
3
+ <saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
4
+ <ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
5
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
6
+ <ds:Reference URI="#pfx852f7331-dd1c-95c3-9cbe-0ab1ebf9c538"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>LQa/IrEdbLE1BHEP3B7KfvOABpg=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>fWg7OauBy7cExPo+GbNVb1e1OopaYc0ke+BYF1N4bpoej86o7U75xOttDN7oz58LhpDZYWcgEvsqX/Jth7Adc3v0bsUEw1h3rFVhGCOnJLS21o1r9cEdkUSbGcJ7jk6EnlxE9s3/puAxkanqzC50hWsIm19Xzu9Li1MN3eDgB9M=</ds:SignatureValue>
7
+ <ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICGzCCAYQCCQCNNcQXom32VDANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzELMAkGA1UECBMCSU4xFTATBgNVBAcTDEluZGlhbmFwb2xpczERMA8GA1UEChMIT25lTG9naW4xDDAKBgNVBAsTA0VuZzAeFw0xNDA0MjMxODQxMDFaFw0xNTA0MjMxODQxMDFaMFIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTjEVMBMGA1UEBxMMSW5kaWFuYXBvbGlzMREwDwYDVQQKEwhPbmVMb2dpbjEMMAoGA1UECxMDRW5nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo6m+QZvYQ/xL0ElLgupK1QDcYL4f5PckwsNgS9pUvV7fzTqCHk8ThLxTk42MQ2McJsOeUJVP728KhymjFCqxgP4VuwRk9rpAl0+mhy6MPdyjyA6G14jrDWS65ysLchK4t/vwpEDz0SQlEoG1kMzllSm7zZS3XregA7DjNaUYQqwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBALM2vGCiQ/vm+a6v40+VX2zdqHA2Q/1vF1ibQzJ54MJCOVWvs+vQXfZFhdm0OPM2IrDU7oqvKPqP6xOAeJK6H0yP7M4YL3fatSvIYmmfyXC9kt3Svz/NyrHzPhUnJ0ye/sUSXxnzQxwcm/9PwAqrQaA3QpQkH57ybF/OoryPe+2h</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>
8
+ <samlp:Status>
9
+ <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
10
+ </samlp:Status>
11
+ <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_d71a3a8e9fcc45c9e9d248ef7049393fc8f04e5f75" Version="2.0" IssueInstant="2014-07-17T01:01:48Z">
12
+ <saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
13
+ <saml:Subject>
14
+ <saml:NameID SPNameQualifier="http://sp.example.com/demo1/metadata.php" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7</saml:NameID>
15
+ <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
16
+ <saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"/>
17
+ </saml:SubjectConfirmation>
18
+ </saml:Subject>
19
+ <saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z">
20
+ <saml:AudienceRestriction>
21
+ <saml:Audience>http://sp.example.com/demo1/metadata.php</saml:Audience>
22
+ </saml:AudienceRestriction>
23
+ </saml:Conditions>
24
+ <saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionNotOnOrAfter="2024-07-17T09:01:48Z" SessionIndex="_be9967abd904ddcae3c0eb4189adbe3f71e327cf93">
25
+ <saml:AuthnContext>
26
+ <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
27
+ </saml:AuthnContext>
28
+ </saml:AuthnStatement>
29
+ <saml:AttributeStatement>
30
+ <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
31
+ <saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
32
+ </saml:Attribute>
33
+ <saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
34
+ <saml:AttributeValue xsi:type="xs:string">test@example.com</saml:AttributeValue>
35
+ </saml:Attribute>
36
+ <saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
37
+ <saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
38
+ <saml:AttributeValue xsi:type="xs:string">examplerole1</saml:AttributeValue>
39
+ </saml:Attribute>
40
+ <saml:Attribute FriendlyName="eduPersonTargetedID" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
41
+ <saml:AttributeValue>
42
+ <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">ZdrjpwEdw22vKoxWAbZB78/gQ7s=</saml:NameID>
43
+ </saml:AttributeValue>
44
+ </saml:Attribute>
45
+ </saml:AttributeStatement>
46
+ </saml:Assertion>
47
+ </samlp:Response>
@@ -0,0 +1 @@
1
+ pVZdd9o4EH3fc/Y/+LiPOcayDTb4BLoU0oSWfBDTbpuXPbI0Bie25Egi0Pz6lQ04kJI03X2CGY/u3LkjjXT8fpVnxgMImXLWNZ0GMt/3/vzjWOI8K8JrkAVnEgwdxGRYOrvmQrCQY5nKkOEcZKhIGPXPx6HbQCGWEoTSUObOkuL1NYXgihOemcZo2DWLZBWTtuvjhFrQScCiXhJbtB00LdIMECIeJIi0TePrlrPG0EulXMCISYWZ0i7kNC3kW6g5RW7ouiFyb0xjCFKlDKtq1VypIrRtXBSNfEFxg3FbSm4TXe4iBw3ItsVPedf8JyFN7DVjZAWg6SDHBYtgDFbQdmMSO14ce22zV8kWVlxEr8wgNyk4g4zPUtYgPLfLIPfY3o09pjKM0pkmtxBbtamsWS6Xy8bSa3Axs12EkI06to6hMp29M3W3DGO7HuiIJbyCG2DGWUpwlj5WJZ+DmnNq9LMZF6ma5y+AO7aDSnALVsQiTpO9M+0qxVOSiuQb4fa4CoktOcfOBrHEu4YEBDACxpfrUdd899b2VyVOBWYy4SKX++bvsQL2oJtTALXktjhN8PcAD6p2bP/McZjO9C78L+JthHsC+YqzBfRGj82bSSa9/qebYezJ9gP58s32rsnRx0m3IrAbXDlqydfms21TN3i9YjL//Cnn7Ie8cu5zhoPoCE6cMXHF5/7t7cC9PBWTy1l0e1VMOVnkE3/+/ezucRrdiEDZI/vz9DJ6OBtM7oeOmDezCN0Or+yTxdlFf6DuOt+DLHO//JgtAnd8FH9U9zduZ8g6YnwX0VORHo2Cs/lq7PkBTfpRNPeP5I/gb3g4oXfnyRKGE7f/TR8i/8OH09ljMD3p1uXs8NejbM/b20y2SGlT7lsDTsGolr0+sGQVHUYLQkDKqtE/g4b97SjcHOfVS8fZsb+djyMyhxybdWz662ArrcYdgZ9m4XqMdlqOH6PEs5otz7cclPgW8RNsdShtuR44zU6bvGlw/o+xVhnRIr4FojbWhdZzNDQ+6iOB1ctCOw2n8qTUSqrQUJecZn1KRSl6T+lN/ddu/k3mNfx+5gFnSVpilN1Yn73XO0zyMAYsQJgvAw2xwsYFV5fsUvQTBaJUz0M76gXra+caSFqkUMortn/rTXMI+dmnDQUdQdPysyyzfgCtClQNc55SOpuUb6C13aULmpazQF92SqRknX7vS91wyXPQgjdghfMig6rneBO0YVyveWbvodvPyqnzqTkrTxDkWiCjMn9xoUd6J2iEF6ptHQgdMQorfZ07ftIKUBIT5DkthAKMvFaLJoD92CNNn5i7pDRVBSt1wDXI9INHz9Peq28iEpIyTruv9M+SC3qlnzy6s0Cr26HgQtWCHQA/8G3PV4tWe7ejp55M27dM718=
@@ -10,6 +10,7 @@ require 'rubygems'
10
10
  require 'bundler'
11
11
  require 'minitest/autorun'
12
12
  require 'mocha/setup'
13
+ require 'timecop'
13
14
 
14
15
  Bundler.require :default, :test
15
16
 
@@ -51,6 +52,10 @@ class Minitest::Test
51
52
  @response_document_valid_signed ||= read_response("valid_response.xml.base64")
52
53
  end
53
54
 
55
+ def response_document_valid_signed_without_x509certificate
56
+ @response_document_valid_signed_without_x509certificate ||= read_response("valid_response_without_x509certificate.xml.base64")
57
+ end
58
+
54
59
  def response_document_without_recipient
55
60
  @response_document_without_recipient ||= read_response("response_with_undefined_recipient.xml.base64")
56
61
  end
@@ -66,6 +71,10 @@ class Minitest::Test
66
71
  @response_document_without_attributes ||= read_response("response_without_attributes.xml.base64")
67
72
  end
68
73
 
74
+ def response_document_without_reference_uri
75
+ @response_document_without_reference_uri ||= read_response("response_without_reference_uri.xml.base64")
76
+ end
77
+
69
78
  def response_document_with_signed_assertion
70
79
  @response_document_with_signed_assertion ||= read_response("response_with_signed_assertion.xml.base64")
71
80
  end
@@ -74,6 +83,10 @@ class Minitest::Test
74
83
  @response_document_with_signed_assertion_2 ||= read_response("response_with_signed_assertion_2.xml.base64")
75
84
  end
76
85
 
86
+ def response_document_with_ds_namespace_at_the_root
87
+ @response_document_with_ds_namespace_at_the_root ||= read_response("response_with_ds_namespace_at_the_root.xml.base64")
88
+ end
89
+
77
90
  def response_document_unsigned
78
91
  @response_document_unsigned ||= read_response("response_unsigned_xml_base64")
79
92
  end
@@ -1,6 +1,5 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
2
  require 'xml_security'
3
- require 'timecop'
4
3
 
5
4
  class XmlSecurityTest < Minitest::Test
6
5
  include XMLSecurity
@@ -69,13 +68,20 @@ class XmlSecurityTest < Minitest::Test
69
68
  assert adfs_document.validate_signature(base64cert, false)
70
69
  end
71
70
 
72
- it "raise validation error when the X509Certificate is missing" do
71
+ it "raise validation error when the X509Certificate is missing and no cert provided" do
73
72
  decoded_response.sub!(/<ds:X509Certificate>.*<\/ds:X509Certificate>/, "")
74
73
  mod_document = XMLSecurity::SignedDocument.new(decoded_response)
75
74
  exception = assert_raises(OneLogin::RubySaml::ValidationError) do
76
75
  mod_document.validate_document("a fingerprint", false) # The fingerprint isn't relevant to this test
77
76
  end
78
- assert_equal("Certificate element missing in response (ds:X509Certificate)", exception.message)
77
+ assert_equal("Certificate element missing in response (ds:X509Certificate) and not cert provided at settings", exception.message)
78
+ end
79
+
80
+ it "invalidaties when the X509Certificate is missing and the cert is provided but mismatches" do
81
+ decoded_response.sub!(/<ds:X509Certificate>.*<\/ds:X509Certificate>/, "")
82
+ mod_document = XMLSecurity::SignedDocument.new(decoded_response)
83
+ cert = OpenSSL::X509::Certificate.new(ruby_saml_cert)
84
+ assert !mod_document.validate_document("a fingerprint", true, :cert => cert) # The fingerprint isn't relevant to this test
79
85
  end
80
86
  end
81
87
 
@@ -215,14 +221,14 @@ class XmlSecurityTest < Minitest::Test
215
221
  assert response.is_valid?
216
222
  end
217
223
 
218
- it "return an empty list when inclusive namespace element is missing" do
224
+ it "return nil when inclusive namespace element is missing" do
219
225
  response = fixture(:no_signature_ns, false)
220
226
  response.slice! %r{<InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="#default saml ds xs xsi"/>}
221
227
 
222
228
  document = XMLSecurity::SignedDocument.new(response)
223
229
  inclusive_namespaces = document.send(:extract_inclusive_namespaces)
224
230
 
225
- assert inclusive_namespaces.empty?
231
+ assert inclusive_namespaces.nil?
226
232
  end
227
233
  end
228
234
 
metadata CHANGED
@@ -1,155 +1,192 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - OneLogin LLC
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2015-07-07 00:00:00.000000000 Z
12
+ date: 2015-10-27 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: uuid
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
- - - "~>"
19
+ - - ~>
18
20
  - !ruby/object:Gem::Version
19
21
  version: '2.3'
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
- - - "~>"
27
+ - - ~>
25
28
  - !ruby/object:Gem::Version
26
29
  version: '2.3'
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: nokogiri
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
- - - ">="
35
+ - - ! '>='
32
36
  - !ruby/object:Gem::Version
33
37
  version: 1.5.10
34
38
  type: :runtime
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
- - - ">="
43
+ - - ! '>='
39
44
  - !ruby/object:Gem::Version
40
45
  version: 1.5.10
41
46
  - !ruby/object:Gem::Dependency
42
47
  name: minitest
43
48
  requirement: !ruby/object:Gem::Requirement
49
+ none: false
44
50
  requirements:
45
- - - "~>"
51
+ - - ~>
46
52
  - !ruby/object:Gem::Version
47
53
  version: '5.5'
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
51
58
  requirements:
52
- - - "~>"
59
+ - - ~>
53
60
  - !ruby/object:Gem::Version
54
61
  version: '5.5'
55
62
  - !ruby/object:Gem::Dependency
56
63
  name: mocha
57
64
  requirement: !ruby/object:Gem::Requirement
65
+ none: false
58
66
  requirements:
59
- - - "~>"
67
+ - - ~>
60
68
  - !ruby/object:Gem::Version
61
69
  version: '0.14'
62
70
  type: :development
63
71
  prerelease: false
64
72
  version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
65
74
  requirements:
66
- - - "~>"
75
+ - - ~>
67
76
  - !ruby/object:Gem::Version
68
77
  version: '0.14'
69
78
  - !ruby/object:Gem::Dependency
70
79
  name: rake
71
80
  requirement: !ruby/object:Gem::Requirement
81
+ none: false
72
82
  requirements:
73
- - - "~>"
83
+ - - ~>
74
84
  - !ruby/object:Gem::Version
75
85
  version: '10'
76
86
  type: :development
77
87
  prerelease: false
78
88
  version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
79
90
  requirements:
80
- - - "~>"
91
+ - - ~>
81
92
  - !ruby/object:Gem::Version
82
93
  version: '10'
83
94
  - !ruby/object:Gem::Dependency
84
95
  name: shoulda
85
96
  requirement: !ruby/object:Gem::Requirement
97
+ none: false
86
98
  requirements:
87
- - - "~>"
99
+ - - ~>
88
100
  - !ruby/object:Gem::Version
89
101
  version: '2.11'
90
102
  type: :development
91
103
  prerelease: false
92
104
  version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
93
106
  requirements:
94
- - - "~>"
107
+ - - ~>
95
108
  - !ruby/object:Gem::Version
96
109
  version: '2.11'
97
110
  - !ruby/object:Gem::Dependency
98
111
  name: simplecov
99
112
  requirement: !ruby/object:Gem::Requirement
113
+ none: false
100
114
  requirements:
101
- - - "~>"
115
+ - - ~>
102
116
  - !ruby/object:Gem::Version
103
117
  version: 0.9.0
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
107
122
  requirements:
108
- - - "~>"
123
+ - - ~>
109
124
  - !ruby/object:Gem::Version
110
125
  version: 0.9.0
111
126
  - !ruby/object:Gem::Dependency
112
127
  name: systemu
113
128
  requirement: !ruby/object:Gem::Requirement
129
+ none: false
114
130
  requirements:
115
- - - "~>"
131
+ - - ~>
116
132
  - !ruby/object:Gem::Version
117
133
  version: '2'
118
134
  type: :development
119
135
  prerelease: false
120
136
  version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
121
138
  requirements:
122
- - - "~>"
139
+ - - ~>
123
140
  - !ruby/object:Gem::Version
124
141
  version: '2'
125
142
  - !ruby/object:Gem::Dependency
126
143
  name: timecop
127
144
  requirement: !ruby/object:Gem::Requirement
145
+ none: false
128
146
  requirements:
129
- - - "<="
147
+ - - <=
130
148
  - !ruby/object:Gem::Version
131
149
  version: 0.6.0
132
150
  type: :development
133
151
  prerelease: false
134
152
  version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
135
154
  requirements:
136
- - - "<="
155
+ - - <=
137
156
  - !ruby/object:Gem::Version
138
157
  version: 0.6.0
139
158
  - !ruby/object:Gem::Dependency
140
- name: pry-byebug
159
+ name: debugger-linecache
141
160
  requirement: !ruby/object:Gem::Requirement
161
+ none: false
142
162
  requirements:
143
- - - ">="
163
+ - - ~>
144
164
  - !ruby/object:Gem::Version
145
- version: '0'
165
+ version: 1.2.0
146
166
  type: :development
147
167
  prerelease: false
148
168
  version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
149
170
  requirements:
150
- - - ">="
171
+ - - ~>
151
172
  - !ruby/object:Gem::Version
152
- version: '0'
173
+ version: 1.2.0
174
+ - !ruby/object:Gem::Dependency
175
+ name: debugger
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ~>
180
+ - !ruby/object:Gem::Version
181
+ version: 1.6.4
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ~>
188
+ - !ruby/object:Gem::Version
189
+ version: 1.6.4
153
190
  description: SAML toolkit for Ruby on Rails
154
191
  email: support@onelogin.com
155
192
  executables: []
@@ -158,9 +195,9 @@ extra_rdoc_files:
158
195
  - LICENSE
159
196
  - README.md
160
197
  files:
161
- - ".document"
162
- - ".gitignore"
163
- - ".travis.yml"
198
+ - .document
199
+ - .gitignore
200
+ - .travis.yml
164
201
  - Gemfile
165
202
  - LICENSE
166
203
  - README.md
@@ -266,15 +303,19 @@ files:
266
303
  - test/responses/response_unsigned_xml_base64
267
304
  - test/responses/response_with_ampersands.xml
268
305
  - test/responses/response_with_ampersands.xml.base64
306
+ - test/responses/response_with_ds_namespace_at_the_root.xml.base64
269
307
  - test/responses/response_with_multiple_attribute_values.xml
270
308
  - test/responses/response_with_saml2_namespace.xml.base64
271
309
  - test/responses/response_with_signed_assertion.xml.base64
272
310
  - test/responses/response_with_signed_assertion_2.xml.base64
273
311
  - test/responses/response_with_undefined_recipient.xml.base64
274
312
  - test/responses/response_without_attributes.xml.base64
313
+ - test/responses/response_without_reference_uri.xml.base64
275
314
  - test/responses/response_wrapped.xml.base64
276
315
  - test/responses/signed_message_encrypted_signed_assertion.xml.base64
277
316
  - test/responses/signed_message_encrypted_unsigned_assertion.xml.base64
317
+ - test/responses/signed_nameid_in_atts.xml
318
+ - test/responses/signed_unqual_nameid_in_atts.xml
278
319
  - test/responses/simple_saml_php.xml
279
320
  - test/responses/starfield_response.xml.base64
280
321
  - test/responses/test_sign.xml
@@ -286,6 +327,7 @@ files:
286
327
  - test/responses/unsigned_message_encrypted_signed_assertion.xml.base64
287
328
  - test/responses/unsigned_message_encrypted_unsigned_assertion.xml.base64
288
329
  - test/responses/valid_response.xml.base64
330
+ - test/responses/valid_response_without_x509certificate.xml.base64
289
331
  - test/saml_message_test.rb
290
332
  - test/settings_test.rb
291
333
  - test/slo_logoutrequest_test.rb
@@ -296,27 +338,28 @@ files:
296
338
  homepage: http://github.com/onelogin/ruby-saml
297
339
  licenses:
298
340
  - MIT
299
- metadata: {}
300
341
  post_install_message:
301
342
  rdoc_options:
302
- - "--charset=UTF-8"
343
+ - --charset=UTF-8
303
344
  require_paths:
304
345
  - lib
305
346
  required_ruby_version: !ruby/object:Gem::Requirement
347
+ none: false
306
348
  requirements:
307
- - - ">="
349
+ - - ! '>='
308
350
  - !ruby/object:Gem::Version
309
351
  version: 1.8.7
310
352
  required_rubygems_version: !ruby/object:Gem::Requirement
353
+ none: false
311
354
  requirements:
312
- - - ">="
355
+ - - ! '>='
313
356
  - !ruby/object:Gem::Version
314
357
  version: '0'
315
358
  requirements: []
316
359
  rubyforge_project: http://www.rubygems.org/gems/ruby-saml
317
- rubygems_version: 2.4.5
360
+ rubygems_version: 1.8.23
318
361
  signing_key:
319
- specification_version: 4
362
+ specification_version: 3
320
363
  summary: SAML Ruby Tookit
321
364
  test_files:
322
365
  - test/certificates/certificate1
@@ -385,15 +428,19 @@ test_files:
385
428
  - test/responses/response_unsigned_xml_base64
386
429
  - test/responses/response_with_ampersands.xml
387
430
  - test/responses/response_with_ampersands.xml.base64
431
+ - test/responses/response_with_ds_namespace_at_the_root.xml.base64
388
432
  - test/responses/response_with_multiple_attribute_values.xml
389
433
  - test/responses/response_with_saml2_namespace.xml.base64
390
434
  - test/responses/response_with_signed_assertion.xml.base64
391
435
  - test/responses/response_with_signed_assertion_2.xml.base64
392
436
  - test/responses/response_with_undefined_recipient.xml.base64
393
437
  - test/responses/response_without_attributes.xml.base64
438
+ - test/responses/response_without_reference_uri.xml.base64
394
439
  - test/responses/response_wrapped.xml.base64
395
440
  - test/responses/signed_message_encrypted_signed_assertion.xml.base64
396
441
  - test/responses/signed_message_encrypted_unsigned_assertion.xml.base64
442
+ - test/responses/signed_nameid_in_atts.xml
443
+ - test/responses/signed_unqual_nameid_in_atts.xml
397
444
  - test/responses/simple_saml_php.xml
398
445
  - test/responses/starfield_response.xml.base64
399
446
  - test/responses/test_sign.xml
@@ -405,6 +452,7 @@ test_files:
405
452
  - test/responses/unsigned_message_encrypted_signed_assertion.xml.base64
406
453
  - test/responses/unsigned_message_encrypted_unsigned_assertion.xml.base64
407
454
  - test/responses/valid_response.xml.base64
455
+ - test/responses/valid_response_without_x509certificate.xml.base64
408
456
  - test/saml_message_test.rb
409
457
  - test/settings_test.rb
410
458
  - test/slo_logoutrequest_test.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 381e8f35422cfa0bbb991272a777f7fdfcdd2081
4
- data.tar.gz: 0371c2cbd05ee2b482fca1feda05a82162550295
5
- SHA512:
6
- metadata.gz: a3553e3802bba3fe72375cf5865dfce58a5bf46efa335a43e49f020ee12691bd099ecc3496be389a2556808ad4428bd79d4c4a51171c582df8ac74d66187e2a0
7
- data.tar.gz: 473180d499b2ffd2648438ce2c4fd103a8b314ccfa18145cb72215edeecc0864f53dbf016ccd66f6025cdb45aca241df14ca3e9f7ec36731ba4a4004ef0b3a6f