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,245 +1,146 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
2
 
3
- class SloLogoutresponseTest < Minitest::Test
3
+ class SloLogoutresponseTest < Test::Unit::TestCase
4
4
 
5
- describe "SloLogoutresponse" do
5
+ context "SloLogoutresponse" do
6
+ settings = OneLogin::RubySaml::Settings.new
6
7
 
7
- let(:settings) { OneLogin::RubySaml::Settings.new }
8
-
9
- before do
8
+ should "create the deflated SAMLResponse URL parameter" do
10
9
  settings.idp_slo_target_url = "http://unauth.com/logout"
11
10
  settings.name_identifier_value = "f00f00"
12
11
  settings.compress_request = true
13
- settings.certificate = ruby_saml_cert_text
14
- settings.private_key = ruby_saml_key_text
15
- end
16
12
 
17
- it "create the deflated SAMLResponse URL parameter" do
18
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings)
19
- assert_match /^http:\/\/unauth\.com\/logout\?SAMLResponse=/, unauth_url
13
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
20
14
 
21
- inflated = decode_saml_response_payload(unauth_url)
22
- assert_match /^<samlp:LogoutResponse/, inflated
23
- end
15
+ assert request.is_valid?
24
16
 
25
- it "support additional params" do
26
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :hello => nil })
27
- assert_match /&hello=$/, unauth_url
17
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id)
18
+ assert unauth_url =~ /^http:\/\/unauth\.com\/logout\?SAMLResponse=/
28
19
 
29
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :foo => "bar" })
30
- assert_match /&foo=bar$/, unauth_url
20
+ inflated = decode_saml_response_payload(unauth_url)
31
21
 
32
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :RelayState => "http://idp.example.com" })
33
- assert_match /&RelayState=http%3A%2F%2Fidp.example.com$/, unauth_url
22
+ assert_match /^<samlp:LogoutResponse/, inflated
34
23
  end
35
24
 
36
- it "RelayState cases" do
37
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :RelayState => nil })
38
- assert !unauth_url.include?('RelayState')
25
+ should "support additional params" do
26
+ settings.idp_slo_target_url = "http://unauth.com/logout"
27
+ settings.name_identifier_value = "f00f00"
28
+ settings.compress_request = true
39
29
 
40
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :RelayState => "http://example.com" })
41
- assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
30
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
42
31
 
43
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { 'RelayState' => nil })
44
- assert !unauth_url.include?('RelayState')
32
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, nil, { :hello => nil })
33
+ assert unauth_url =~ /&hello=$/
45
34
 
46
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { 'RelayState' => "http://example.com" })
47
- assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
35
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, nil, { :foo => "bar" })
36
+ assert unauth_url =~ /&foo=bar$/
37
+
38
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, nil, { :RelayState => "http://idp.example.com" })
39
+ assert unauth_url =~ /&RelayState=http%3A%2F%2Fidp.example.com$/
48
40
  end
49
41
 
50
- it "set InResponseTo to the ID from the logout request" do
51
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, '_c0348950-935b-0131-1060-782bcb56fcaa')
42
+ should "set InResponseTo to the ID from the logout request" do
43
+ settings.idp_slo_target_url = "http://unauth.com/logout"
44
+ settings.name_identifier_value = "f00f00"
45
+ settings.compress_request = true
46
+
47
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
48
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id)
52
49
 
53
50
  inflated = decode_saml_response_payload(unauth_url)
51
+
54
52
  assert_match /InResponseTo='_c0348950-935b-0131-1060-782bcb56fcaa'/, inflated
55
53
  end
56
54
 
57
- it "set a custom successful logout message on the response" do
58
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, "Custom Logout Message")
59
-
60
- inflated = decode_saml_response_payload(unauth_url)
61
- assert_match /<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated
62
- end
55
+ should "set a custom successful logout message on the response" do
56
+ settings.idp_slo_target_url = "http://unauth.com/logout"
57
+ settings.name_identifier_value = "f00f00"
58
+ settings.compress_request = true
63
59
 
64
- it "set a custom logout message and an status on the response" do
65
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, "Custom Logout Message", {}, "urn:oasis:names:tc:SAML:2.0:status:PartialLogout")
60
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
61
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, "Custom Logout Message")
66
62
 
67
63
  inflated = decode_saml_response_payload(unauth_url)
64
+
68
65
  assert_match /<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated
69
- assert_match /<samlp:StatusCode Value='urn:oasis:names:tc:SAML:2.0:status:PartialLogout/, inflated
70
66
  end
71
67
 
72
- describe "when the settings indicate to sign (embedded) logout response" do
73
-
74
- before do
68
+ context "when the settings indicate to sign (embebed) the logout response" do
69
+ should "create a signed logout response" do
70
+ settings = OneLogin::RubySaml::Settings.new
75
71
  settings.compress_response = false
72
+ settings.idp_slo_target_url = "http://example.com?field=value"
76
73
  settings.security[:logout_responses_signed] = true
77
74
  settings.security[:embed_sign] = true
78
- end
79
-
80
- it "doesn't sign through create_xml_document" do
81
- unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
82
- inflated = unauth_res.create_xml_document(settings).to_s
83
-
84
- refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
85
- refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
86
- refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
87
- end
75
+ settings.certificate = ruby_saml_cert_text
76
+ settings.private_key = ruby_saml_key_text
88
77
 
89
- it "sign unsigned request" do
90
- unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
91
- unauth_res_doc = unauth_res.create_xml_document(settings)
92
- inflated = unauth_res_doc.to_s
93
-
94
- refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
95
- refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
96
- refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
97
-
98
- inflated = unauth_res.sign_document(unauth_res_doc, settings).to_s
99
-
100
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
101
- assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
102
- assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
103
- end
104
-
105
- it "signs through create_logout_response_xml_doc" do
106
- unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
107
- inflated = unauth_res.create_logout_response_xml_doc(settings).to_s
108
-
109
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
110
- assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
111
- assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
112
- end
113
-
114
- it "create a signed logout response" do
115
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message")
78
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
79
+ params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
116
80
 
117
81
  response_xml = Base64.decode64(params["SAMLResponse"])
118
82
  assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
119
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/, response_xml
120
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#sha1'\/>/, response_xml
83
+ response_xml =~ /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/
84
+ response_xml =~ /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/
121
85
  end
122
86
 
123
- it "create a signed logout response with 256 digest and signature methods" do
124
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
125
- settings.security[:digest_method] = XMLSecurity::Document::SHA256
126
-
127
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message")
128
-
129
- response_xml = Base64.decode64(params["SAMLResponse"])
130
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
131
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256'\/>/, response_xml
132
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha256'\/>/, response_xml
133
- end
134
-
135
- it "create a signed logout response with 512 digest and signature method RSA_SHA384" do
136
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
87
+ should "create a signed logout response with 256 digest and signature methods" do
88
+ settings = OneLogin::RubySaml::Settings.new
89
+ settings.compress_response = false
90
+ settings.idp_slo_target_url = "http://example.com?field=value"
91
+ settings.security[:logout_responses_signed] = true
92
+ settings.security[:embed_sign] = true
93
+ settings.security[:signature_method] = XMLSecurity::Document::SHA256
137
94
  settings.security[:digest_method] = XMLSecurity::Document::SHA512
95
+ settings.certificate = ruby_saml_cert_text
96
+ settings.private_key = ruby_saml_key_text
138
97
 
139
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message")
98
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
99
+ params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
140
100
 
141
101
  response_xml = Base64.decode64(params["SAMLResponse"])
142
102
  assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
143
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha384'\/>/, response_xml
144
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha512'\/>/, response_xml
103
+ response_xml =~ /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256'\/>/
104
+ response_xml =~ /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha512'\/>/
145
105
  end
146
106
  end
147
107
 
148
- describe "#create_params when the settings indicate to sign the logout response" do
149
-
150
- let(:cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
151
-
152
- before do
108
+ context "when the settings indicate to sign the logout response" do
109
+ should "create a signature parameter" do
110
+ settings = OneLogin::RubySaml::Settings.new
153
111
  settings.compress_response = false
112
+ settings.idp_slo_target_url = "http://example.com?field=value"
113
+ settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
154
114
  settings.security[:logout_responses_signed] = true
155
115
  settings.security[:embed_sign] = false
156
- end
157
-
158
- it "create a signature parameter with RSA_SHA1 and validate it" do
159
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
116
+ settings.security[:signature_method] = XMLSecurity::Document::SHA1
117
+ settings.certificate = ruby_saml_cert_text
118
+ settings.private_key = ruby_saml_key_text
160
119
 
161
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
162
- assert params['SAMLResponse']
163
- assert params[:RelayState]
120
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
121
+ params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
164
122
  assert params['Signature']
165
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA1
166
-
167
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
168
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
169
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
170
-
171
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
172
- assert_equal signature_algorithm, OpenSSL::Digest::SHA1
173
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
174
- end
123
+ assert params['SigAlg'] == XMLSecurity::Document::SHA1
175
124
 
176
- it "create a signature parameter with RSA_SHA256 /SHA256 and validate it" do
177
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
178
-
179
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
180
- assert params['SAMLResponse']
181
- assert params[:RelayState]
125
+ # signature_method only affects the embedeed signature
126
+ settings.security[:signature_method] = XMLSecurity::Document::SHA256
127
+ params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
182
128
  assert params['Signature']
183
-
184
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA256
185
-
186
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
187
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
188
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
189
-
190
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
191
- assert_equal signature_algorithm, OpenSSL::Digest::SHA256
192
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
129
+ assert params['SigAlg'] == XMLSecurity::Document::SHA1
193
130
  end
131
+ end
194
132
 
195
- it "create a signature parameter with RSA_SHA384 / SHA384 and validate it" do
196
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
197
-
198
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
199
- assert params['SAMLResponse']
200
- assert params[:RelayState]
201
- assert params['Signature']
202
-
203
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA384
204
-
205
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
206
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
207
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
208
-
209
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
210
- assert_equal signature_algorithm, OpenSSL::Digest::SHA384
211
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
212
- end
213
-
214
- it "create a signature parameter with RSA_SHA512 / SHA512 and validate it" do
215
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA512
216
-
217
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
218
- assert params['SAMLResponse']
219
- assert params[:RelayState]
220
- assert params['Signature']
221
-
222
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA512
133
+ end
223
134
 
224
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
225
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
226
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
135
+ def decode_saml_response_payload(unauth_url)
136
+ payload = CGI.unescape(unauth_url.split("SAMLResponse=").last)
137
+ decoded = Base64.decode64(payload)
227
138
 
228
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
229
- assert_equal signature_algorithm, OpenSSL::Digest::SHA512
230
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
231
- end
232
- end
233
-
234
- describe "#manipulate response_id" do
235
- it "be able to modify the response id" do
236
- logoutresponse = OneLogin::RubySaml::SloLogoutresponse.new
237
- response_id = logoutresponse.response_id
238
- assert_equal response_id, logoutresponse.uuid
239
- logoutresponse.uuid = "new_uuid"
240
- assert_equal logoutresponse.response_id, logoutresponse.uuid
241
- assert_equal "new_uuid", logoutresponse.response_id
242
- end
243
- end
139
+ zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
140
+ inflated = zstream.inflate(decoded)
141
+ zstream.finish
142
+ zstream.close
143
+ inflated
244
144
  end
145
+
245
146
  end
data/test/test_helper.rb CHANGED
@@ -1,14 +1,9 @@
1
1
  require 'rubygems'
2
- require 'minitest/autorun'
3
- require 'shoulda'
2
+ require 'bundler'
3
+ require 'test/unit'
4
4
  require 'mocha/setup'
5
- require 'timecop'
6
5
 
7
- if RUBY_VERSION < '1.9'
8
- require 'uuid'
9
- else
10
- require 'securerandom'
11
- end
6
+ Bundler.require :default, :test
12
7
 
13
8
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
9
  $LOAD_PATH.unshift(File.dirname(__FILE__))
@@ -16,7 +11,7 @@ require 'ruby-saml'
16
11
 
17
12
  ENV["ruby-saml/testing"] = "1"
18
13
 
19
- class Minitest::Test
14
+ class Test::Unit::TestCase
20
15
  def fixture(document, base64 = true)
21
16
  response = Dir.glob(File.join(File.dirname(__FILE__), "responses", "#{document}*")).first
22
17
  if base64 && response =~ /\.xml$/
@@ -26,48 +21,32 @@ class Minitest::Test
26
21
  end
27
22
  end
28
23
 
29
- def random_id
30
- RUBY_VERSION < '1.9' ? "_#{UUID.new.generate}" : "_#{SecureRandom.uuid}"
31
- end
32
-
33
- def read_invalid_response(response)
34
- File.read(File.join(File.dirname(__FILE__), "responses", "invalids", response))
35
- end
36
-
37
- def read_response(response)
38
- File.read(File.join(File.dirname(__FILE__), "responses", response))
39
- end
40
-
41
- def read_certificate(certificate)
42
- File.read(File.join(File.dirname(__FILE__), "certificates", certificate))
43
- end
44
-
45
24
  def response_document
46
- @response_document ||= read_response('response1.xml.base64')
25
+ @response_document ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response1.xml.base64'))
47
26
  end
48
27
 
49
28
  def response_document_2
50
- @response_document2 ||= read_response('response2.xml.base64')
29
+ @response_document2 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response2.xml.base64'))
51
30
  end
52
31
 
53
32
  def response_document_3
54
- @response_document3 ||= read_response('response3.xml.base64')
33
+ @response_document3 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response3.xml.base64'))
55
34
  end
56
35
 
57
36
  def response_document_4
58
- @response_document4 ||= read_response('response4.xml.base64')
37
+ @response_document4 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response4.xml.base64'))
59
38
  end
60
39
 
61
40
  def response_document_5
62
- @response_document5 ||= read_response('response5.xml.base64')
41
+ @response_document5 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response5.xml.base64'))
63
42
  end
64
43
 
65
44
  def r1_response_document_6
66
- @response_document6 ||= read_response('r1_response6.xml.base64')
45
+ @response_document6 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'r1_response6.xml.base64'))
67
46
  end
68
47
 
69
48
  def ampersands_response
70
- @ampersands_resposne ||= read_response('response_with_ampersands.xml.base64')
49
+ @ampersands_response ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_with_ampersands.xml.base64'))
71
50
  end
72
51
 
73
52
  def response_document_6
@@ -77,20 +56,8 @@ class Minitest::Test
77
56
  Base64.encode64(doc)
78
57
  end
79
58
 
80
- def response_document_wrapped
81
- @response_document_wrapped ||= read_response("response_wrapped.xml.base64")
82
- end
83
-
84
- def response_document_valid_signed
85
- response_document_valid_signed ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'valid_response.xml.base64'))
86
- end
87
-
88
- def response_document_valid_signed_without_x509certificate
89
- @response_document_valid_signed_without_x509certificate ||= read_response("valid_response_without_x509certificate.xml.base64")
90
- end
91
-
92
- def response_document_without_recipient
93
- @response_document_without_recipient ||= read_response("response_with_undefined_recipient.xml.base64")
59
+ def response_document_7
60
+ @response_document7 ||= Base64.encode64(File.read(File.join(File.dirname(__FILE__), 'responses', 'response_no_cert_and_encrypted_attrs.xml')))
94
61
  end
95
62
 
96
63
  def wrapped_response_2
@@ -101,87 +68,45 @@ class Minitest::Test
101
68
  @signature_fingerprint1 ||= "C5:19:85:D9:47:F1:BE:57:08:20:25:05:08:46:EB:27:F6:CA:B7:83"
102
69
  end
103
70
 
104
- def signature_fingerprint_valid_res
105
- @signature_fingerprint1 ||= "4b68c453c7d994aad9025c99d5efcf566287fe8d"
106
- end
107
-
108
71
  def signature_1
109
- @signature1 ||= read_certificate('certificate1')
72
+ @signature1 ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'certificate1'))
110
73
  end
111
74
 
112
75
  def r1_signature_2
113
- @signature2 ||= read_certificate('r1_certificate2_base64')
76
+ @signature2 ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'r1_certificate2_base64'))
114
77
  end
115
78
 
116
- def valid_cert
117
- @signature_valid_cert ||= read_certificate('ruby-saml.crt')
79
+ def idp_metadata
80
+ @idp_metadata ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'idp_descriptor.xml'))
118
81
  end
119
82
 
120
- def valid_key
121
- @signature_valid_cert ||= read_certificate('ruby-saml.key')
122
- end
123
-
124
- def response_with_multiple_attribute_statements
125
- @response_with_multiple_attribute_statements = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_statements))
126
- end
127
-
128
- def response_multiple_attr_values
129
- @response_multiple_attr_values = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
83
+ def logout_request_document
84
+ unless @logout_request_document
85
+ xml = File.read(File.join(File.dirname(__FILE__), 'responses', 'slo_request.xml'))
86
+ deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
87
+ @logout_request_document = Base64.encode64(deflated)
88
+ end
89
+ @logout_request_document
130
90
  end
131
91
 
132
92
  def ruby_saml_cert
133
93
  @ruby_saml_cert ||= OpenSSL::X509::Certificate.new(ruby_saml_cert_text)
134
94
  end
135
95
 
136
- def ruby_saml_cert2
137
- @ruby_saml_cert2 ||= OpenSSL::X509::Certificate.new(ruby_saml_cert_text2)
138
- end
139
-
140
96
  def ruby_saml_cert_fingerprint
141
97
  @ruby_saml_cert_fingerprint ||= Digest::SHA1.hexdigest(ruby_saml_cert.to_der).scan(/../).join(":")
142
98
  end
143
99
 
144
100
  def ruby_saml_cert_text
145
- read_certificate("ruby-saml.crt")
146
- end
147
-
148
- def ruby_saml_cert_text2
149
- read_certificate("ruby-saml-2.crt")
150
- end
151
-
152
- def ruby_saml_key_text
153
- read_certificate("ruby-saml.key")
101
+ File.read(File.join(File.dirname(__FILE__), 'certificates', 'ruby-saml.crt'))
154
102
  end
155
103
 
156
104
  def ruby_saml_key
157
105
  @ruby_saml_key ||= OpenSSL::PKey::RSA.new(ruby_saml_key_text)
158
106
  end
159
107
 
160
- def read_certificate(certificate)
161
- File.read(File.join(File.dirname(__FILE__), "certificates", certificate))
162
- end
163
-
164
- def decode_saml_request_payload(unauth_url)
165
- payload = CGI.unescape(unauth_url.split("SAMLRequest=").last)
166
- decoded = Base64.decode64(payload)
167
-
168
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
169
- inflated = zstream.inflate(decoded)
170
- zstream.finish
171
- zstream.close
172
- inflated
108
+ def ruby_saml_key_text
109
+ File.read(File.join(File.dirname(__FILE__), 'certificates', 'ruby-saml.key'))
173
110
  end
174
111
 
175
- # decodes a base64 encoded SAML response for use in SloLogoutresponse tests
176
- #
177
- def decode_saml_response_payload(unauth_url)
178
- payload = CGI.unescape(unauth_url.split("SAMLResponse=").last)
179
- decoded = Base64.decode64(payload)
180
-
181
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
182
- inflated = zstream.inflate(decoded)
183
- zstream.finish
184
- zstream.close
185
- inflated
186
- end
187
112
  end