ruby-saml 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.

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