ruby-saml 0.8.18 → 0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -6
  4. data/Gemfile +2 -12
  5. data/README.md +363 -35
  6. data/Rakefile +14 -0
  7. data/changelog.md +22 -9
  8. data/lib/onelogin/ruby-saml/attribute_service.rb +34 -0
  9. data/lib/onelogin/ruby-saml/attributes.rb +26 -64
  10. data/lib/onelogin/ruby-saml/authrequest.rb +47 -93
  11. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +87 -0
  12. data/lib/onelogin/ruby-saml/logoutrequest.rb +36 -100
  13. data/lib/onelogin/ruby-saml/logoutresponse.rb +25 -35
  14. data/lib/onelogin/ruby-saml/metadata.rb +46 -16
  15. data/lib/onelogin/ruby-saml/response.rb +63 -373
  16. data/lib/onelogin/ruby-saml/saml_message.rb +78 -0
  17. data/lib/onelogin/ruby-saml/settings.rb +54 -122
  18. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +25 -71
  19. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +37 -102
  20. data/lib/onelogin/ruby-saml/utils.rb +32 -199
  21. data/lib/onelogin/ruby-saml/version.rb +1 -1
  22. data/lib/ruby-saml.rb +5 -2
  23. data/lib/schemas/{saml20assertion_schema.xsd → saml-schema-assertion-2.0.xsd} +283 -283
  24. data/lib/schemas/saml-schema-authn-context-2.0.xsd +23 -0
  25. data/lib/schemas/saml-schema-authn-context-types-2.0.xsd +821 -0
  26. data/lib/schemas/saml-schema-metadata-2.0.xsd +339 -0
  27. data/lib/schemas/{saml20protocol_schema.xsd → saml-schema-protocol-2.0.xsd} +302 -302
  28. data/lib/schemas/sstc-metadata-attr.xsd +35 -0
  29. data/lib/schemas/sstc-saml-attribute-ext.xsd +25 -0
  30. data/lib/schemas/sstc-saml-metadata-algsupport-v1.0.xsd +41 -0
  31. data/lib/schemas/sstc-saml-metadata-ui-v1.0.xsd +89 -0
  32. data/lib/schemas/{xenc_schema.xsd → xenc-schema.xsd} +1 -11
  33. data/lib/schemas/xml.xsd +287 -0
  34. data/lib/schemas/{xmldsig_schema.xsd → xmldsig-core-schema.xsd} +0 -9
  35. data/lib/xml_security.rb +83 -235
  36. data/ruby-saml.gemspec +1 -0
  37. data/test/idp_metadata_parser_test.rb +54 -0
  38. data/test/logoutrequest_test.rb +68 -155
  39. data/test/logoutresponse_test.rb +43 -32
  40. data/test/metadata_test.rb +87 -0
  41. data/test/request_test.rb +102 -99
  42. data/test/response_test.rb +181 -495
  43. data/test/responses/idp_descriptor.xml +3 -0
  44. data/test/responses/logoutresponse_fixtures.rb +7 -8
  45. data/test/responses/response_no_cert_and_encrypted_attrs.xml +29 -0
  46. data/test/responses/response_with_multiple_attribute_values.xml +1 -1
  47. data/test/responses/slo_request.xml +4 -0
  48. data/test/settings_test.rb +25 -112
  49. data/test/slo_logoutrequest_test.rb +40 -50
  50. data/test/slo_logoutresponse_test.rb +86 -185
  51. data/test/test_helper.rb +27 -102
  52. data/test/xml_security_test.rb +114 -337
  53. metadata +30 -81
  54. data/lib/onelogin/ruby-saml/setting_error.rb +0 -6
  55. data/test/certificates/certificate.der +0 -0
  56. data/test/certificates/formatted_certificate +0 -14
  57. data/test/certificates/formatted_chained_certificate +0 -42
  58. data/test/certificates/formatted_private_key +0 -12
  59. data/test/certificates/formatted_rsa_private_key +0 -12
  60. data/test/certificates/invalid_certificate1 +0 -1
  61. data/test/certificates/invalid_certificate2 +0 -1
  62. data/test/certificates/invalid_certificate3 +0 -12
  63. data/test/certificates/invalid_chained_certificate1 +0 -1
  64. data/test/certificates/invalid_private_key1 +0 -1
  65. data/test/certificates/invalid_private_key2 +0 -1
  66. data/test/certificates/invalid_private_key3 +0 -10
  67. data/test/certificates/invalid_rsa_private_key1 +0 -1
  68. data/test/certificates/invalid_rsa_private_key2 +0 -1
  69. data/test/certificates/invalid_rsa_private_key3 +0 -10
  70. data/test/certificates/ruby-saml-2.crt +0 -15
  71. data/test/requests/logoutrequest_fixtures.rb +0 -47
  72. data/test/responses/encrypted_new_attack.xml.base64 +0 -1
  73. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  74. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  75. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  76. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  77. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  78. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  79. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  80. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  81. data/test/responses/response_with_concealed_signed_assertion.xml +0 -51
  82. data/test/responses/response_with_doubled_signed_assertion.xml +0 -49
  83. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  84. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  85. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  86. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  87. data/test/responses/response_wrapped.xml.base64 +0 -150
  88. data/test/responses/valid_response.xml.base64 +0 -1
  89. data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
  90. data/test/utils_test.rb +0 -231
@@ -1,197 +1,112 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
1
+ require 'test_helper'
2
+ require 'xml_security'
2
3
 
3
- class XmlSecurityTest < Minitest::Test
4
+ class XmlSecurityTest < Test::Unit::TestCase
4
5
  include XMLSecurity
5
6
 
6
- describe "XmlSecurity" do
7
-
8
- let(:decoded_response) { Base64.decode64(response_document_without_recipient) }
9
- let(:document) { XMLSecurity::SignedDocument.new(decoded_response) }
10
- let(:settings) { OneLogin::RubySaml::Settings.new() }
11
-
12
- before do
13
- @base64cert = document.elements["//ds:X509Certificate"].text
7
+ context "XmlSecurity" do
8
+ setup do
9
+ @document = XMLSecurity::SignedDocument.new(Base64.decode64(response_document))
10
+ @base64cert = @document.elements["//ds:X509Certificate"].text
14
11
  end
15
12
 
16
- it "should run validate without throwing NS related exceptions" do
17
- assert !document.validate_signature(@base64cert, true)
13
+ should "should run validate without throwing NS related exceptions" do
14
+ assert !@document.validate_signature(@base64cert, true)
18
15
  end
19
16
 
20
- it "should run validate with throwing NS related exceptions" do
21
- assert_raises(OneLogin::RubySaml::ValidationError) do
22
- document.validate_signature(@base64cert, false)
17
+ should "should run validate with throwing NS related exceptions" do
18
+ assert_raise(OneLogin::RubySaml::ValidationError) do
19
+ @document.validate_signature(@base64cert, false)
23
20
  end
24
21
  end
25
22
 
26
- it "not raise an error when softly validating the document multiple times" do
27
- 2.times { assert_equal document.validate_signature(@base64cert, true), false }
23
+ should "not raise an error when softly validating the document multiple times" do
24
+ assert_nothing_raised do
25
+ 2.times { @document.validate_signature(@base64cert, true) }
26
+ end
28
27
  end
29
28
 
30
- it "not raise an error when softly validating the document and the X509Certificate is missing" do
31
- decoded_response.sub!(/<ds:X509Certificate>.*<\/ds:X509Certificate>/, "")
32
- mod_document = XMLSecurity::SignedDocument.new(decoded_response)
33
- assert !mod_document.validate_document("a fingerprint", true) # The fingerprint isn't relevant to this test
29
+ should "not raise an error when softly validating the document and the X509Certificate is missing" do
30
+ response = Base64.decode64(response_document)
31
+ response.sub!(/<ds:X509Certificate>.*<\/ds:X509Certificate>/, "")
32
+ document = XMLSecurity::SignedDocument.new(response)
33
+ assert_nothing_raised do
34
+ assert !document.validate_document("a fingerprint", true) # The fingerprint isn't relevant to this test
35
+ end
34
36
  end
35
37
 
36
- it "should raise Fingerprint mismatch" do
37
- exception = assert_raises(OneLogin::RubySaml::ValidationError) do
38
- document.validate_document("no:fi:ng:er:pr:in:t", false)
38
+ should "should raise Fingerprint mismatch" do
39
+ exception = assert_raise(OneLogin::RubySaml::ValidationError) do
40
+ @document.validate_document("no:fi:ng:er:pr:in:t", false)
39
41
  end
40
42
  assert_equal("Fingerprint mismatch", exception.message)
43
+ assert @document.errors.include? "Fingerprint mismatch"
41
44
  end
42
45
 
43
- it "should raise Digest mismatch" do
44
- exception = assert_raises(OneLogin::RubySaml::ValidationError) do
45
- document.validate_signature(@base64cert, false)
46
+ should "should raise Digest mismatch" do
47
+ exception = assert_raise(OneLogin::RubySaml::ValidationError) do
48
+ @document.validate_signature(@base64cert, false)
46
49
  end
47
50
  assert_equal("Digest mismatch", exception.message)
51
+ assert @document.errors.include? "Digest mismatch"
48
52
  end
49
53
 
50
- it "should raise Key validation error" do
51
- decoded_response.sub!("<ds:DigestValue>pJQ7MS/ek4KRRWGmv/H43ReHYMs=</ds:DigestValue>",
54
+ should "should raise Key validation error" do
55
+ response = Base64.decode64(response_document)
56
+ response.sub!("<ds:DigestValue>pJQ7MS/ek4KRRWGmv/H43ReHYMs=</ds:DigestValue>",
52
57
  "<ds:DigestValue>b9xsAXLsynugg3Wc1CI3kpWku+0=</ds:DigestValue>")
53
- mod_document = XMLSecurity::SignedDocument.new(decoded_response)
54
- base64cert = mod_document.elements["//ds:X509Certificate"].text
55
- exception = assert_raises(OneLogin::RubySaml::ValidationError) do
56
- mod_document.validate_signature(base64cert, false)
58
+ document = XMLSecurity::SignedDocument.new(response)
59
+ base64cert = document.elements["//ds:X509Certificate"].text
60
+ exception = assert_raise(OneLogin::RubySaml::ValidationError) do
61
+ document.validate_signature(base64cert, false)
57
62
  end
58
63
  assert_equal("Key validation error", exception.message)
64
+ assert document.errors.include? "Key validation error"
59
65
  end
60
66
 
61
- it "correctly obtain the digest method with alternate namespace declaration" do
62
- adfs_document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_xmlns, false))
63
- base64cert = adfs_document.elements["//X509Certificate"].text
64
- assert adfs_document.validate_signature(base64cert, false)
67
+ should "correctly obtain the digest method with alternate namespace declaration" do
68
+ document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_xmlns, false))
69
+ base64cert = document.elements["//X509Certificate"].text
70
+ assert document.validate_signature(base64cert, false)
65
71
  end
66
72
 
67
- it "raise validation error when the X509Certificate is missing and no cert provided" do
68
- decoded_response.sub!(/<ds:X509Certificate>.*<\/ds:X509Certificate>/, "")
69
- mod_document = XMLSecurity::SignedDocument.new(decoded_response)
70
- exception = assert_raises(OneLogin::RubySaml::ValidationError) do
71
- mod_document.validate_document("a fingerprint", false) # The fingerprint isn't relevant to this test
73
+ should "raise validation error when the X509Certificate is missing" do
74
+ response = Base64.decode64(response_document)
75
+ response.sub!(/<ds:X509Certificate>.*<\/ds:X509Certificate>/, "")
76
+ document = XMLSecurity::SignedDocument.new(response)
77
+ exception = assert_raise(OneLogin::RubySaml::ValidationError) do
78
+ document.validate_document("a fingerprint", false) # The fingerprint isn't relevant to this test
72
79
  end
73
- assert_equal("Certificate element missing in response (ds:X509Certificate) and not cert provided at settings", exception.message)
74
- end
75
-
76
- it "invalidaties when the X509Certificate is missing and the cert is provided but mismatches" do
77
- decoded_response.sub!(/<ds:X509Certificate>.*<\/ds:X509Certificate>/, "")
78
- mod_document = XMLSecurity::SignedDocument.new(decoded_response)
79
- cert = OpenSSL::X509::Certificate.new(ruby_saml_cert)
80
- assert !mod_document.validate_document("a fingerprint", true, :cert => cert) # The fingerprint isn't relevant to this test
81
- end
82
- end
83
-
84
- describe "#canon_algorithm" do
85
- it "C14N_EXCLUSIVE_1_0" do
86
- canon_algorithm = Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
87
- assert_equal canon_algorithm, XMLSecurity::BaseDocument.new.canon_algorithm("http://www.w3.org/2001/10/xml-exc-c14n#")
88
- assert_equal canon_algorithm, XMLSecurity::BaseDocument.new.canon_algorithm("http://www.w3.org/2001/10/xml-exc-c14n#WithComments")
89
- assert_equal canon_algorithm, XMLSecurity::BaseDocument.new.canon_algorithm("other")
90
- end
91
-
92
- it "C14N_1_0" do
93
- canon_algorithm = Nokogiri::XML::XML_C14N_1_0
94
- assert_equal canon_algorithm, XMLSecurity::BaseDocument.new.canon_algorithm("http://www.w3.org/TR/2001/REC-xml-c14n-20010315")
95
- assert_equal canon_algorithm, XMLSecurity::BaseDocument.new.canon_algorithm("http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments")
96
- end
97
-
98
- it "XML_C14N_1_1" do
99
- canon_algorithm = Nokogiri::XML::XML_C14N_1_1
100
- assert_equal canon_algorithm, XMLSecurity::BaseDocument.new.canon_algorithm("http://www.w3.org/2006/12/xml-c14n11")
101
- assert_equal canon_algorithm, XMLSecurity::BaseDocument.new.canon_algorithm("http://www.w3.org/2006/12/xml-c14n11#WithComments")
80
+ assert_equal("Certificate element missing in response (ds:X509Certificate)", exception.message)
102
81
  end
103
82
  end
104
83
 
105
- describe "#algorithm" do
106
- it "SHA1" do
107
- alg = OpenSSL::Digest::SHA1
108
- assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2000/09/xmldsig#rsa-sha1")
109
- assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2000/09/xmldsig#sha1")
110
- assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("other")
84
+ context "Algorithms" do
85
+ should "validate using SHA1" do
86
+ @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha1, false))
87
+ assert @document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
111
88
  end
112
89
 
113
- it "SHA256" do
114
- alg = OpenSSL::Digest::SHA256
115
- assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256")
116
- assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2001/04/xmldsig-more#sha256")
90
+ should "validate using SHA256" do
91
+ @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha256, false))
92
+ assert @document.validate_document("28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA")
117
93
  end
118
94
 
119
- it "SHA384" do
120
- alg = OpenSSL::Digest::SHA384
121
- assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384")
122
- assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2001/04/xmldsig-more#sha384")
95
+ should "validate using SHA384" do
96
+ @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha384, false))
97
+ assert @document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
123
98
  end
124
99
 
125
- it "SHA512" do
126
- alg = OpenSSL::Digest::SHA512
127
- assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512")
128
- assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2001/04/xmldsig-more#sha512")
100
+ should "validate using SHA512" do
101
+ @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha512, false))
102
+ assert @document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
129
103
  end
130
104
  end
131
105
 
132
- describe "Fingerprint Algorithms" do
133
- let(:response_fingerprint_test) { OneLogin::RubySaml::Response.new(fixture(:adfs_response_sha1, false)) }
134
-
135
- it "validate using SHA1" do
136
- sha1_fingerprint = "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72"
137
- sha1_fingerprint_downcase = "f13c6b80905a030e6c913e5d15faddb016454872"
138
-
139
- assert response_fingerprint_test.document.validate_document(sha1_fingerprint)
140
- assert response_fingerprint_test.document.validate_document(sha1_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA1)
141
-
142
- assert response_fingerprint_test.document.validate_document(sha1_fingerprint_downcase)
143
- assert response_fingerprint_test.document.validate_document(sha1_fingerprint_downcase, true, :fingerprint_alg => XMLSecurity::Document::SHA1)
144
- end
145
-
146
- it "validate using SHA256" do
147
- sha256_fingerprint = "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21"
148
-
149
- assert !response_fingerprint_test.document.validate_document(sha256_fingerprint)
150
- assert response_fingerprint_test.document.validate_document(sha256_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA256)
151
- end
152
-
153
- it "validate using SHA384" do
154
- sha384_fingerprint = "98:FE:17:90:31:E7:68:18:8A:65:4D:DA:F5:76:E2:09:97:BE:8B:E3:7E:AA:8D:63:64:7C:0C:38:23:9A:AC:A2:EC:CE:48:A6:74:4D:E0:4C:50:80:40:B4:8D:55:14:14"
155
-
156
- assert !response_fingerprint_test.document.validate_document(sha384_fingerprint)
157
- assert response_fingerprint_test.document.validate_document(sha384_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA384)
158
- end
159
-
160
- it "validate using SHA512" do
161
- sha512_fingerprint = "5A:AE:BA:D0:BA:9D:1E:25:05:01:1E:1A:C9:E9:FF:DB:ED:FA:6E:F7:52:EB:45:49:BD:DB:06:D8:A3:7E:CC:63:3A:04:A2:DD:DF:EE:61:05:D9:58:95:2A:77:17:30:4B:EB:4A:9F:48:4A:44:1C:D0:9E:0B:1E:04:77:FD:A3:D2"
106
+ context "XmlSecurity::SignedDocument" do
162
107
 
163
- assert !response_fingerprint_test.document.validate_document(sha512_fingerprint)
164
- assert response_fingerprint_test.document.validate_document(sha512_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA512)
165
- end
166
-
167
- end
168
-
169
- describe "Signature Algorithms" do
170
- it "validate using SHA1" do
171
- document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha1, false))
172
- assert document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
173
- end
174
-
175
- it "validate using SHA256" do
176
- document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha256, false))
177
- assert document.validate_document("28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA")
178
- end
179
-
180
- it "validate using SHA384" do
181
- document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha384, false))
182
- assert document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
183
- end
184
-
185
- it "validate using SHA512" do
186
- document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha512, false))
187
- assert document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
188
- end
189
- end
190
-
191
- describe "XmlSecurity::SignedDocument" do
192
-
193
- describe "#extract_inclusive_namespaces" do
194
- it "support explicit namespace resolution for exclusive canonicalization" do
108
+ context "#extract_inclusive_namespaces" do
109
+ should "support explicit namespace resolution for exclusive canonicalization" do
195
110
  response = fixture(:open_saml_response, false)
196
111
  document = XMLSecurity::SignedDocument.new(response)
197
112
  inclusive_namespaces = document.send(:extract_inclusive_namespaces)
@@ -199,7 +114,7 @@ class XmlSecurityTest < Minitest::Test
199
114
  assert_equal %w[ xs ], inclusive_namespaces
200
115
  end
201
116
 
202
- it "support implicit namespace resolution for exclusive canonicalization" do
117
+ should "support implicit namespace resolution for exclusive canonicalization" do
203
118
  response = fixture(:no_signature_ns, false)
204
119
  document = XMLSecurity::SignedDocument.new(response)
205
120
  inclusive_namespaces = document.send(:extract_inclusive_namespaces)
@@ -207,245 +122,107 @@ class XmlSecurityTest < Minitest::Test
207
122
  assert_equal %w[ #default saml ds xs xsi ], inclusive_namespaces
208
123
  end
209
124
 
210
- it 'support inclusive canonicalization' do
211
- skip('test not yet implemented')
125
+ should_eventually 'support inclusive canonicalization' do
126
+
212
127
  response = OneLogin::RubySaml::Response.new(fixture("tdnf_response.xml"))
213
128
  response.stubs(:conditions).returns(nil)
214
129
  assert !response.is_valid?
130
+ settings = OneLogin::RubySaml::Settings.new
215
131
  assert !response.is_valid?
216
132
  response.settings = settings
217
133
  assert !response.is_valid?
218
134
  settings.idp_cert_fingerprint = "e6 38 9a 20 b7 4f 13 db 6a bc b1 42 6a e7 52 1d d6 56 d4 1b".upcase.gsub(" ", ":")
219
- assert response.is_valid?
135
+ assert response.validate!
220
136
  end
221
137
 
222
- it "return nil when inclusive namespace element is missing" do
138
+ should "return an empty list when inclusive namespace element is missing" do
223
139
  response = fixture(:no_signature_ns, false)
224
140
  response.slice! %r{<InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="#default saml ds xs xsi"/>}
225
141
 
226
142
  document = XMLSecurity::SignedDocument.new(response)
227
143
  inclusive_namespaces = document.send(:extract_inclusive_namespaces)
228
144
 
229
- assert inclusive_namespaces.nil?
145
+ assert inclusive_namespaces.empty?
230
146
  end
231
147
  end
232
148
 
233
- describe "XMLSecurity::DSIG" do
234
- before do
235
- settings.idp_sso_target_url = "https://idp.example.com/sso"
236
- settings.protocol_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
237
- settings.idp_slo_target_url = "https://idp.example.com/slo",
238
- settings.sp_entity_id = "https://sp.example.com/saml2"
239
- settings.assertion_consumer_service_url = "https://sp.example.com/acs"
240
- settings.single_logout_service_url = "https://sp.example.com/sls"
241
- end
149
+ context "XMLSecurity::DSIG" do
150
+ should "sign a AuthNRequest" do
151
+ settings = OneLogin::RubySaml::Settings.new({
152
+ :idp_sso_target_url => "https://idp.example.com/sso",
153
+ :protocol_binding => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
154
+ :issuer => "https://sp.example.com/saml2",
155
+ :assertion_consumer_service_url => "https://sp.example.com/acs"
156
+ })
242
157
 
243
- it "sign an AuthNRequest" do
244
158
  request = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
245
159
  request.sign_document(ruby_saml_key, ruby_saml_cert)
246
- # verify our signature
247
- signed_doc = XMLSecurity::SignedDocument.new(request.to_s)
248
- assert signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
249
160
 
250
- request2 = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
251
- request2.sign_document(ruby_saml_key, ruby_saml_cert_text)
252
161
  # verify our signature
253
- signed_doc2 = XMLSecurity::SignedDocument.new(request2.to_s)
254
- assert signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
162
+ signed_doc = XMLSecurity::SignedDocument.new(request.to_s)
163
+ signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
255
164
  end
256
165
 
257
- it "sign an AuthNRequest with certificate as text" do
258
- request = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
259
- request.sign_document(ruby_saml_key, ruby_saml_cert_text)
166
+ should "sign a LogoutRequest" do
167
+ settings = OneLogin::RubySaml::Settings.new({
168
+ :idp_slo_target_url => "https://idp.example.com/slo",
169
+ :protocol_binding => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
170
+ :issuer => "https://sp.example.com/saml2",
171
+ :single_logout_service_url => "https://sp.example.com/sls"
172
+ })
173
+
174
+ request = OneLogin::RubySaml::Logoutrequest.new.create_logout_request_xml_doc(settings)
175
+ request.sign_document(ruby_saml_key, ruby_saml_cert)
260
176
 
261
177
  # verify our signature
262
178
  signed_doc = XMLSecurity::SignedDocument.new(request.to_s)
263
- assert signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
179
+ signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
264
180
  end
265
181
 
266
- it "sign a LogoutRequest" do
267
- logout_request = OneLogin::RubySaml::Logoutrequest.new.create_logout_request_xml_doc(settings)
268
- logout_request.sign_document(ruby_saml_key, ruby_saml_cert)
269
- # verify our signature
270
- signed_doc = XMLSecurity::SignedDocument.new(logout_request.to_s)
271
- assert signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
272
-
273
- logout_request2 = OneLogin::RubySaml::Logoutrequest.new.create_logout_request_xml_doc(settings)
274
- logout_request2.sign_document(ruby_saml_key, ruby_saml_cert_text)
275
- # verify our signature
276
- signed_doc2 = XMLSecurity::SignedDocument.new(logout_request2.to_s)
277
- signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
278
- assert signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
279
- end
182
+ should "sign a LogoutResponse" do
183
+ settings = OneLogin::RubySaml::Settings.new({
184
+ :idp_slo_target_url => "https://idp.example.com/slo",
185
+ :protocol_binding => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
186
+ :issuer => "https://sp.example.com/saml2",
187
+ :single_logout_service_url => "https://sp.example.com/sls"
188
+ })
280
189
 
281
- it "sign a LogoutResponse" do
282
- logout_response = OneLogin::RubySaml::SloLogoutresponse.new.create_logout_response_xml_doc(settings, 'request_id_example', "Custom Logout Message")
283
- logout_response.sign_document(ruby_saml_key, ruby_saml_cert)
284
- # verify our signature
285
- signed_doc = XMLSecurity::SignedDocument.new(logout_response.to_s)
286
- assert signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
190
+ response = OneLogin::RubySaml::SloLogoutresponse.new.create_logout_response_xml_doc(settings, 'request_id_example', "Custom Logout Message")
191
+ response.sign_document(ruby_saml_key, ruby_saml_cert)
287
192
 
288
- logout_response2 = OneLogin::RubySaml::SloLogoutresponse.new.create_logout_response_xml_doc(settings, 'request_id_example', "Custom Logout Message")
289
- logout_response2.sign_document(ruby_saml_key, ruby_saml_cert_text)
290
193
  # verify our signature
291
- signed_doc2 = XMLSecurity::SignedDocument.new(logout_response2.to_s)
292
- signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
293
- assert signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
194
+ signed_doc = XMLSecurity::SignedDocument.new(response.to_s)
195
+ signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
294
196
  end
295
197
  end
296
198
 
297
- describe "StarfieldTMS" do
298
- before do
199
+ context "StarfieldTMS" do
200
+ setup do
299
201
  @response = OneLogin::RubySaml::Response.new(fixture(:starfield_response))
300
- @response.settings = OneLogin::RubySaml::Settings.new( :idp_cert_fingerprint => "8D:BA:53:8E:A3:B6:F9:F1:69:6C:BB:D9:D8:BD:41:B3:AC:4F:9D:4D")
202
+ @response.settings = OneLogin::RubySaml::Settings.new(
203
+ :idp_cert_fingerprint => "8D:BA:53:8E:A3:B6:F9:F1:69:6C:BB:D9:D8:BD:41:B3:AC:4F:9D:4D"
204
+ )
301
205
  end
302
206
 
303
- it "be able to validate a good response" do
207
+ should "be able to validate a good response" do
304
208
  Timecop.freeze Time.parse('2012-11-28 17:55:00 UTC') do
305
209
  assert @response.validate!
306
210
  end
307
211
  end
308
212
 
309
- it "fail before response is valid" do
213
+ should "fail before response is valid" do
310
214
  Timecop.freeze Time.parse('2012-11-20 17:55:00 UTC') do
311
215
  assert ! @response.is_valid?
312
216
  end
313
217
  end
314
218
 
315
- it "fail after response expires" do
219
+ should "fail after response expires" do
316
220
  Timecop.freeze Time.parse('2012-11-30 17:55:00 UTC') do
317
221
  assert ! @response.is_valid?
318
222
  end
319
223
  end
320
224
  end
321
225
 
322
- describe '#validate_document' do
323
- describe 'with valid document' do
324
- describe 'when response has signed message and assertion' do
325
- let(:document_data) { read_response('response_with_signed_message_and_assertion.xml') }
326
- let(:document) { OneLogin::RubySaml::Response.new(document_data).document }
327
- let(:fingerprint) { '4b68c453c7d994aad9025c99d5efcf566287fe8d' }
328
-
329
- it 'is valid' do
330
- assert document.validate_document(fingerprint, true), 'Document should be valid'
331
- end
332
- end
333
-
334
- describe 'when response has signed assertion' do
335
- let(:document_data) { read_response('response_with_signed_assertion_3.xml') }
336
- let(:document) { OneLogin::RubySaml::Response.new(document_data).document }
337
- let(:fingerprint) { '4b68c453c7d994aad9025c99d5efcf566287fe8d' }
338
-
339
- it 'is valid' do
340
- assert document.validate_document(fingerprint, true), 'Document should be valid'
341
- end
342
- end
343
- end
344
-
345
- describe 'signature_wrapping_attack' do
346
- let(:document_data) { read_invalid_response("signature_wrapping_attack.xml.base64") }
347
- let(:document) { OneLogin::RubySaml::Response.new(document_data).document }
348
- let(:fingerprint) { 'afe71c28ef740bc87425be13a2263d37971da1f9' }
349
-
350
- it 'is invalid' do
351
- assert !document.validate_document(fingerprint, true), 'Document should be invalid'
352
- end
353
- end
354
-
355
- describe 'signature wrapping attack - doubled SAML response body' do
356
- let(:document_data) { read_invalid_response("response_with_doubled_signed_assertion.xml") }
357
- let(:document) { OneLogin::RubySaml::Response.new(document_data) }
358
- let(:fingerprint) { '4b68c453c7d994aad9025c99d5efcf566287fe8d' }
359
-
360
- it 'is valid, but the unsigned information is ignored in favour of the signed information' do
361
- assert document.document.validate_document(fingerprint, true), 'Document should be valid'
362
- assert_equal 'someone@example.org', document.name_id, 'Document should expose only signed, valid details'
363
- end
364
- end
365
-
366
- describe 'signature wrapping attack - concealed SAML response body' do
367
- let(:document_data) { read_invalid_response("response_with_concealed_signed_assertion.xml") }
368
- let(:document) { OneLogin::RubySaml::Response.new(document_data) }
369
- let(:fingerprint) { '4b68c453c7d994aad9025c99d5efcf566287fe8d' }
370
-
371
- it 'is valid, but fails to retrieve information' do
372
- assert document.document.validate_document(fingerprint, true), 'Document should be valid'
373
- assert document.name_id.nil?, 'Document should expose only signed, valid details'
374
- end
375
- end
376
-
377
- describe 'when response has no cert and you provide cert' do
378
- let(:document) { OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate).document }
379
- let(:idp_cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
380
- let(:options) { {} }
381
-
382
- it 'is valid' do
383
- options[:cert] = idp_cert
384
- assert document.document.validate_document(idp_cert, true, options), 'Document should be valid'
385
- end
386
-
387
- it 'is valid if cert text instead x509cert provided' do
388
- options[:cert] = ruby_saml_cert_text
389
- assert document.document.validate_document(idp_cert, true, options), 'Document should be valid'
390
- end
391
- end
392
-
393
- describe 'when response has no cert and you dont provide cert' do
394
- let(:document) { OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate).document }
395
- let(:options) { {} }
396
- let(:idp_cert) { nil }
397
-
398
- it 'is invalid' do
399
- options[:cert] = idp_cert
400
- assert !document.document.validate_document(idp_cert, true, options), 'Document should not be valid'
401
- end
402
-
403
- it 'is invalid and error raised' do
404
- options[:cert] = idp_cert
405
- assert_raises(OneLogin::RubySaml::ValidationError) do
406
- document.document.validate_document(idp_cert, false, options)
407
- end
408
- end
409
- end
410
- end
411
-
412
- describe '#validate_document_with_cert' do
413
- describe 'with valid document ' do
414
- describe 'when response has cert' do
415
- let(:document_data) { read_response('response_with_signed_message_and_assertion.xml') }
416
- let(:document) { OneLogin::RubySaml::Response.new(document_data).document }
417
- let(:idp_cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
418
- let(:fingerprint) { '4b68c453c7d994aad9025c99d5efcf566287fe8d' }
419
-
420
- it 'is valid' do
421
- assert document.validate_document_with_cert(idp_cert), 'Document should be valid'
422
- end
423
- end
424
-
425
- describe 'when response has no cert and you provide cert' do
426
- let(:document) { OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate).document }
427
- let(:idp_cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
428
-
429
- it 'is valid' do
430
- assert document.validate_document_with_cert(idp_cert), 'Document should be valid'
431
- end
432
- end
433
-
434
- describe 'when response has no cert and you dont provide cert' do
435
- let(:document) { OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate).document }
436
- let(:idp_cert) { nil }
437
-
438
- it 'is invalid' do
439
- assert !document.validate_document_with_cert(idp_cert), 'Document should not be valid'
440
- end
441
-
442
- it 'is invalid and error raised' do
443
- assert_raises(OneLogin::RubySaml::ValidationError) do
444
- document.validate_document_with_cert(idp_cert, false)
445
- end
446
- end
447
- end
448
- end
449
- end
450
226
  end
227
+
451
228
  end