ruby-saml 1.4.3 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ruby-saml might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +8 -1
- data/changelog.md +9 -0
- data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +16 -1
- data/lib/onelogin/ruby-saml/logoutresponse.rb +1 -1
- data/lib/onelogin/ruby-saml/response.rb +24 -7
- data/lib/onelogin/ruby-saml/saml_message.rb +1 -1
- data/lib/onelogin/ruby-saml/utils.rb +16 -6
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/xml_security.rb +4 -2
- data/test/idp_metadata_parser_test.rb +15 -4
- data/test/logoutresponse_test.rb +1 -0
- data/test/metadata/no_idp_descriptor.xml +21 -0
- data/test/response_test.rb +14 -2
- data/test/responses/response_double_status_code.xml.base64 +1 -0
- data/test/responses/unsigned_encrypted_adfs.xml +23 -0
- data/test/test_helper.rb +8 -0
- data/test/xml_security_test.rb +37 -8
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6958524060034d6eaaf5c0f968711ecdc45e2bd
|
4
|
+
data.tar.gz: f1714aa26982ce596b8e07f2e20a8637611d7523
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cb2ee3fefaec17210a0087dbadc68698b4fa9969d20c81512c9d1904bf941a59179a73b2d46ed52c38867f0c201b82e9f8cdd0f50b114103b7fe72cfcbb7bdc
|
7
|
+
data.tar.gz: ed45f61f08919d846edb627699ed1679f5d7e8c1c5136a4703d3c9129bc7259e9f761a1a8fc12bb439bd5e96128069c5c0b3b9115e1f8d38e55a874523793cec
|
data/README.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Ruby SAML [](http://travis-ci.org/onelogin/ruby-saml) [](https://coveralls.io/r/onelogin/ruby-saml?branch=master%0A) [](http://badge.fury.io/rb/ruby-saml)
|
2
2
|
|
3
|
+
## Updating from 1.4.2 to 1.4.3
|
4
|
+
|
5
|
+
Version `1.4.3` introduces Recipient validation of SubjectConfirmation elements.
|
6
|
+
The 'Recipient' value is compared with the settings.assertion_consumer_service_url
|
7
|
+
value.
|
8
|
+
If you want to skip that validation, add the :skip_recipient_check option to the
|
9
|
+
initialize method of the Response object.
|
10
|
+
|
3
11
|
## Updating from 1.3.x to 1.4.X
|
4
12
|
|
5
13
|
Version `1.4.0` is a recommended update for all Ruby SAML users as it includes security improvements.
|
@@ -169,7 +177,6 @@ def saml_settings
|
|
169
177
|
|
170
178
|
settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
|
171
179
|
settings.issuer = "http://#{request.host}/saml/metadata"
|
172
|
-
settings.idp_sso_target_url = "https://app.onelogin.com/saml/metadata/#{OneLoginAppId}"
|
173
180
|
settings.idp_entity_id = "https://app.onelogin.com/saml/metadata/#{OneLoginAppId}"
|
174
181
|
settings.idp_sso_target_url = "https://app.onelogin.com/trust/saml2/http-post/sso/#{OneLoginAppId}"
|
175
182
|
settings.idp_slo_target_url = "https://app.onelogin.com/trust/saml2/http-redirect/slo/#{OneLoginAppId}"
|
data/changelog.md
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
# RubySaml Changelog
|
2
|
+
### 1.5.0 (August 31, 2017)
|
3
|
+
* [#400](https://github.com/onelogin/ruby-saml/pull/400) When validating Signature use stored IdP certficate if Signature contains no info about Certificate
|
4
|
+
* [#402](https://github.com/onelogin/ruby-saml/pull/402) Fix validate_response_state method that rejected SAMLResponses when using idp_cert_multi and idp_cert and idp_cert_fingerprint were not provided.
|
5
|
+
* [#411](https://github.com/onelogin/ruby-saml/pull/411) Allow space in Base64 string
|
6
|
+
* [#407](https://github.com/onelogin/ruby-saml/issues/407) Improve IdpMetadataParser raising an ArgumentError when parser method receive a metadata string with no IDPSSODescriptor element.
|
7
|
+
* [#374](https://github.com/onelogin/ruby-saml/issues/374) Support more than one level of StatusCode
|
8
|
+
* [#405](https://github.com/onelogin/ruby-saml/pull/405) Support ADFS encrypted key (Accept KeyInfo nodes with no ds namespace)
|
9
|
+
|
10
|
+
|
2
11
|
### 1.4.3 (May 18, 2017)
|
3
12
|
* Added SubjectConfirmation Recipient validation
|
4
13
|
* [#393](https://github.com/onelogin/ruby-saml/pull/393) Implement IdpMetadataParser#parse_to_hash
|
@@ -102,6 +102,10 @@ module OneLogin
|
|
102
102
|
@options = options
|
103
103
|
@entity_descriptor = nil
|
104
104
|
|
105
|
+
if idpsso_descriptor.nil?
|
106
|
+
raise ArgumentError.new("idp_metadata may contain an IDPSSODescriptor element")
|
107
|
+
end
|
108
|
+
|
105
109
|
{
|
106
110
|
:idp_entity_id => idp_entity_id,
|
107
111
|
:name_identifier_format => idp_name_id_format,
|
@@ -164,6 +168,16 @@ module OneLogin
|
|
164
168
|
path << "[@entityID=\"#{entity_id}\"]"
|
165
169
|
end
|
166
170
|
|
171
|
+
def idpsso_descriptor
|
172
|
+
unless entity_descriptor.nil?
|
173
|
+
return REXML::XPath.first(
|
174
|
+
entity_descriptor,
|
175
|
+
"md:IDPSSODescriptor",
|
176
|
+
namespace
|
177
|
+
)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
167
181
|
# @return [String|nil] IdP Entity ID value if exists
|
168
182
|
#
|
169
183
|
def idp_entity_id
|
@@ -335,7 +349,8 @@ module OneLogin
|
|
335
349
|
)
|
336
350
|
end
|
337
351
|
else
|
338
|
-
|
352
|
+
# symbolize keys of certificates and pass it on
|
353
|
+
parsed_metadata[:idp_cert_multi] = Hash[certificates.map { |k, v| [k.to_sym, v] }]
|
339
354
|
end
|
340
355
|
end
|
341
356
|
|
@@ -168,7 +168,7 @@ module OneLogin
|
|
168
168
|
|
169
169
|
return append_error("No issuer in settings of the logout response") if settings.issuer.nil?
|
170
170
|
|
171
|
-
if settings.idp_cert_fingerprint.nil? && settings.idp_cert.nil?
|
171
|
+
if settings.idp_cert_fingerprint.nil? && settings.idp_cert.nil? && settings.idp_cert_multi.nil?
|
172
172
|
return append_error("No fingerprint or certificate on settings of the logout response")
|
173
173
|
end
|
174
174
|
|
@@ -37,6 +37,7 @@ module OneLogin
|
|
37
37
|
# with the :skip_conditions, or allow a clock_drift when checking dates with :allowed_clock_drift
|
38
38
|
# or :matches_request_id that will validate that the response matches the ID of the request,
|
39
39
|
# or skip the subject confirmation validation with the :skip_subject_confirmation option
|
40
|
+
# or skip the recipient validation of the subject confirmation element with :skip_recipient_check option
|
40
41
|
def initialize(response, options = {})
|
41
42
|
raise ArgumentError.new("Response cannot be nil") if response.nil?
|
42
43
|
|
@@ -206,7 +207,23 @@ module OneLogin
|
|
206
207
|
)
|
207
208
|
if nodes.size == 1
|
208
209
|
node = nodes[0]
|
209
|
-
node.attributes["Value"] if node && node.attributes
|
210
|
+
code = node.attributes["Value"] if node && node.attributes
|
211
|
+
|
212
|
+
unless code == "urn:oasis:names:tc:SAML:2.0:status:Success"
|
213
|
+
nodes = REXML::XPath.match(
|
214
|
+
document,
|
215
|
+
"/p:Response/p:Status/p:StatusCode/p:StatusCode",
|
216
|
+
{ "p" => PROTOCOL }
|
217
|
+
)
|
218
|
+
statuses = nodes.collect do |node|
|
219
|
+
node.attributes["Value"]
|
220
|
+
end
|
221
|
+
extra_code = statuses.join(" | ")
|
222
|
+
if extra_code
|
223
|
+
code = "#{code} | #{extra_code}"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
code
|
210
227
|
end
|
211
228
|
end
|
212
229
|
end
|
@@ -411,7 +428,7 @@ module OneLogin
|
|
411
428
|
|
412
429
|
return append_error("No settings on response") if settings.nil?
|
413
430
|
|
414
|
-
if settings.idp_cert_fingerprint.nil? && settings.idp_cert.nil?
|
431
|
+
if settings.idp_cert_fingerprint.nil? && settings.idp_cert.nil? && settings.idp_cert_multi.nil?
|
415
432
|
return append_error("No fingerprint or certificate on settings")
|
416
433
|
end
|
417
434
|
|
@@ -650,13 +667,13 @@ module OneLogin
|
|
650
667
|
|
651
668
|
now = Time.now.utc
|
652
669
|
|
653
|
-
if not_before && (now + allowed_clock_drift) < not_before
|
654
|
-
error_msg = "Current time is earlier than NotBefore condition #{
|
670
|
+
if not_before && (now_with_drift = now + allowed_clock_drift) < not_before
|
671
|
+
error_msg = "Current time is earlier than NotBefore condition (#{now_with_drift} < #{not_before})"
|
655
672
|
return append_error(error_msg)
|
656
673
|
end
|
657
674
|
|
658
|
-
if not_on_or_after && now >= (not_on_or_after + allowed_clock_drift)
|
659
|
-
error_msg = "Current time is on or after NotOnOrAfter condition (#{now} >= #{
|
675
|
+
if not_on_or_after && now >= (not_on_or_after_with_drift = not_on_or_after + allowed_clock_drift)
|
676
|
+
error_msg = "Current time is on or after NotOnOrAfter condition (#{now} >= #{not_on_or_after_with_drift})"
|
660
677
|
return append_error(error_msg)
|
661
678
|
end
|
662
679
|
|
@@ -813,7 +830,7 @@ module OneLogin
|
|
813
830
|
opts[:cert] = settings.get_idp_cert
|
814
831
|
fingerprint = settings.get_fingerprint
|
815
832
|
|
816
|
-
unless fingerprint && doc.validate_document(fingerprint, @soft, opts)
|
833
|
+
unless fingerprint && doc.validate_document(fingerprint, @soft, opts)
|
817
834
|
return append_error(error_msg)
|
818
835
|
end
|
819
836
|
else
|
@@ -129,7 +129,7 @@ module OneLogin
|
|
129
129
|
# @return [true, false] whether or not the string is base64 encoded
|
130
130
|
#
|
131
131
|
def base64_encoded?(string)
|
132
|
-
!!string.gsub(/[\r\n]|\\r|\\n/, "").match(BASE64_FORMAT)
|
132
|
+
!!string.gsub(/[\r\n]|\\r|\\n|\s/, "").match(BASE64_FORMAT)
|
133
133
|
end
|
134
134
|
|
135
135
|
# Inflate method
|
@@ -87,7 +87,15 @@ module OneLogin
|
|
87
87
|
# @return [String] The status error message
|
88
88
|
def self.status_error_msg(error_msg, status_code = nil, status_message = nil)
|
89
89
|
unless status_code.nil?
|
90
|
-
|
90
|
+
if status_code.include? "|"
|
91
|
+
status_codes = status_code.split(' | ')
|
92
|
+
values = status_codes.collect do |status_code|
|
93
|
+
status_code.split(':').last
|
94
|
+
end
|
95
|
+
printable_code = values.join(" => ")
|
96
|
+
else
|
97
|
+
printable_code = status_code.split(':').last
|
98
|
+
end
|
91
99
|
error_msg << ', was ' + printable_code
|
92
100
|
end
|
93
101
|
|
@@ -131,23 +139,25 @@ module OneLogin
|
|
131
139
|
def self.retrieve_symmetric_key(encrypt_data, private_key)
|
132
140
|
encrypted_key = REXML::XPath.first(
|
133
141
|
encrypt_data,
|
134
|
-
"./ds:KeyInfo/xenc:EncryptedKey
|
135
|
-
//xenc:EncryptedKey[@Id=$id]",
|
142
|
+
"./ds:KeyInfo/xenc:EncryptedKey | ./KeyInfo/xenc:EncryptedKey | //xenc:EncryptedKey[@Id=$id]",
|
136
143
|
{ "ds" => DSIG, "xenc" => XENC },
|
137
|
-
{ "id" =>
|
144
|
+
{ "id" => self.retrieve_symetric_key_reference(encrypt_data) }
|
138
145
|
)
|
139
146
|
|
140
147
|
encrypted_symmetric_key_element = REXML::XPath.first(
|
141
148
|
encrypted_key,
|
142
149
|
"./xenc:CipherData/xenc:CipherValue",
|
143
|
-
|
150
|
+
"xenc" => XENC
|
144
151
|
)
|
152
|
+
|
145
153
|
cipher_text = Base64.decode64(encrypted_symmetric_key_element.text)
|
154
|
+
|
146
155
|
encrypt_method = REXML::XPath.first(
|
147
156
|
encrypted_key,
|
148
157
|
"./xenc:EncryptionMethod",
|
149
|
-
|
158
|
+
"xenc" => XENC
|
150
159
|
)
|
160
|
+
|
151
161
|
algorithm = encrypt_method.attributes['Algorithm']
|
152
162
|
retrieve_plaintext(cipher_text, private_key, algorithm)
|
153
163
|
end
|
data/lib/xml_security.rb
CHANGED
@@ -260,9 +260,11 @@ module XMLSecurity
|
|
260
260
|
# check saml response cert matches provided idp cert
|
261
261
|
if idp_cert.to_pem != cert.to_pem
|
262
262
|
return false
|
263
|
+
end
|
264
|
+
else
|
265
|
+
base64_cert = Base64.encode64(idp_cert.to_pem)
|
263
266
|
end
|
264
|
-
|
265
|
-
end
|
267
|
+
validate_signature(base64_cert, true)
|
266
268
|
end
|
267
269
|
|
268
270
|
def validate_signature(base64_cert, soft = true)
|
@@ -202,10 +202,10 @@ class IdpMetadataParserTest < Minitest::Test
|
|
202
202
|
assert_nil settings.idp_cert_fingerprint
|
203
203
|
assert_nil settings.idp_cert
|
204
204
|
assert_equal 2, settings.idp_cert_multi.size
|
205
|
-
assert settings.idp_cert_multi.key?(
|
206
|
-
assert_equal 2, settings.idp_cert_multi[
|
207
|
-
assert settings.idp_cert_multi.key?(
|
208
|
-
assert_equal 1, settings.idp_cert_multi[
|
205
|
+
assert settings.idp_cert_multi.key?(:signing)
|
206
|
+
assert_equal 2, settings.idp_cert_multi[:signing].size
|
207
|
+
assert settings.idp_cert_multi.key?(:encryption)
|
208
|
+
assert_equal 1, settings.idp_cert_multi[:encryption].size
|
209
209
|
end
|
210
210
|
end
|
211
211
|
|
@@ -332,4 +332,15 @@ class IdpMetadataParserTest < Minitest::Test
|
|
332
332
|
assert_equal ["AuthToken", "SSOStartPage"], @settings.idp_attribute_names
|
333
333
|
end
|
334
334
|
end
|
335
|
+
|
336
|
+
describe "parsing metadata with no IDPSSODescriptor element" do
|
337
|
+
before do
|
338
|
+
@idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
|
339
|
+
@idp_metadata = no_idp_metadata_descriptor
|
340
|
+
end
|
341
|
+
|
342
|
+
it "raise due no IDPSSODescriptor element" do
|
343
|
+
assert_raises(ArgumentError) { @idp_metadata_parser.parse(@idp_metadata) }
|
344
|
+
end
|
345
|
+
end
|
335
346
|
end
|
data/test/logoutresponse_test.rb
CHANGED
@@ -90,6 +90,7 @@ class RubySamlTest < Minitest::Test
|
|
90
90
|
it "invalidate logout response when initiated with no idp cert or fingerprint" do
|
91
91
|
settings.idp_cert_fingerprint = nil
|
92
92
|
settings.idp_cert = nil
|
93
|
+
settings.idp_cert_multi = nil
|
93
94
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document, settings)
|
94
95
|
assert !logoutresponse.validate
|
95
96
|
assert_includes logoutresponse.errors, "No fingerprint or certificate on settings of the logout response"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<md:EntityDescriptor entityID="https://sp.example.com/sp.xml" validUntil="2014-04-17T18:02:33.910Z" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
|
3
|
+
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol" AuthnRequestsSigned="true">
|
4
|
+
<md:KeyDescriptor use="signing">
|
5
|
+
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
6
|
+
<ds:X509Data>
|
7
|
+
<ds:X509Certificate>LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURxekNDQXhTZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBRENCaGpFTE1Ba0dBMVVFQmhNQ1FWVXgKRERBS0JnTlZCQWdUQTA1VFZ6RVBNQTBHQTFVRUJ4TUdVM2xrYm1WNU1Rd3dDZ1lEVlFRS0RBTlFTVlF4Q1RBSApCZ05WQkFzTUFERVlNQllHQTFVRUF3d1BiR0YzY21WdVkyVndhWFF1WTI5dE1TVXdJd1lKS29aSWh2Y05BUWtCCkRCWnNZWGR5Wlc1alpTNXdhWFJBWjIxaGFXd3VZMjl0TUI0WERURXlNRFF4T1RJeU5UUXhPRm9YRFRNeU1EUXgKTkRJeU5UUXhPRm93Z1lZeEN6QUpCZ05WQkFZVEFrRlZNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVApCbE41Wkc1bGVURU1NQW9HQTFVRUNnd0RVRWxVTVFrd0J3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psCmJtTmxjR2wwTG1OdmJURWxNQ01HQ1NxR1NJYjNEUUVKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnYKYlRDQm56QU5CZ2txaGtpRzl3MEJBUUVGQUFPQmpRQXdnWWtDZ1lFQXFqaWUzUjJvaStwRGFldndJeXMvbWJVVApubkdsa3h0ZGlrcnExMXZleHd4SmlQTmhtaHFSVzNtVXVKRXpsbElkVkw2RW14R1lUcXBxZjkzSGxoa3NhZUowCjhVZ2pQOVVtTVlyaFZKdTFqY0ZXVjdmei9yKzIxL2F3VG5EVjlzTVlRcXVJUllZeTdiRzByMU9iaXdkb3ZudGsKN2dGSTA2WjB2WmFjREU1Ym9xVUNBd0VBQWFPQ0FTVXdnZ0VoTUFrR0ExVWRFd1FDTUFBd0N3WURWUjBQQkFRRApBZ1VnTUIwR0ExVWREZ1FXQkJTUk9OOEdKOG8rOGpnRnRqa3R3WmRxeDZCUnlUQVRCZ05WSFNVRUREQUtCZ2dyCkJnRUZCUWNEQVRBZEJnbGdoa2dCaHZoQ0FRMEVFQllPVkdWemRDQllOVEE1SUdObGNuUXdnYk1HQTFVZEl3U0IKcXpDQnFJQVVrVGpmQmlmS1B2STRCYlk1TGNHWGFzZWdVY21oZ1l5a2dZa3dnWVl4Q3pBSkJnTlZCQVlUQWtGVgpNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVEJsTjVaRzVsZVRFTU1Bb0dBMVVFQ2d3RFVFbFVNUWt3CkJ3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psYm1ObGNHbDBMbU52YlRFbE1DTUdDU3FHU0liM0RRRUoKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnZiWUlCQVRBTkJna3Foa2lHOXcwQkFRc0ZBQU9CZ1FDRQpUQWVKVERTQVc2ejFVRlRWN1FyZWg0VUxGT1JhajkrZUN1RjNLV0RIYyswSVFDajlyZG5ERzRRL3dmNy9yYVEwCkpuUFFDU0NkclBMSmV5b1BIN1FhVHdvYUY3ZHpWdzRMQ3N5TkpURld4NGNNNTBWdzZSNWZET2dpQzhic2ZmUzgKQkptb3VscnJaRE5OVmpHOG1XNmNMeHJZdlZRT3JSVmVjQ0ZJZ3NzQ2JBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=</ds:X509Certificate>
|
8
|
+
</ds:X509Data>
|
9
|
+
</ds:KeyInfo>
|
10
|
+
</md:KeyDescriptor>
|
11
|
+
<md:KeyDescriptor use="encryption">
|
12
|
+
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
13
|
+
<ds:X509Data>
|
14
|
+
<ds:X509Certificate>LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURxekNDQXhTZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBRENCaGpFTE1Ba0dBMVVFQmhNQ1FWVXgKRERBS0JnTlZCQWdUQTA1VFZ6RVBNQTBHQTFVRUJ4TUdVM2xrYm1WNU1Rd3dDZ1lEVlFRS0RBTlFTVlF4Q1RBSApCZ05WQkFzTUFERVlNQllHQTFVRUF3d1BiR0YzY21WdVkyVndhWFF1WTI5dE1TVXdJd1lKS29aSWh2Y05BUWtCCkRCWnNZWGR5Wlc1alpTNXdhWFJBWjIxaGFXd3VZMjl0TUI0WERURXlNRFF4T1RJeU5UUXhPRm9YRFRNeU1EUXgKTkRJeU5UUXhPRm93Z1lZeEN6QUpCZ05WQkFZVEFrRlZNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVApCbE41Wkc1bGVURU1NQW9HQTFVRUNnd0RVRWxVTVFrd0J3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psCmJtTmxjR2wwTG1OdmJURWxNQ01HQ1NxR1NJYjNEUUVKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnYKYlRDQm56QU5CZ2txaGtpRzl3MEJBUUVGQUFPQmpRQXdnWWtDZ1lFQXFqaWUzUjJvaStwRGFldndJeXMvbWJVVApubkdsa3h0ZGlrcnExMXZleHd4SmlQTmhtaHFSVzNtVXVKRXpsbElkVkw2RW14R1lUcXBxZjkzSGxoa3NhZUowCjhVZ2pQOVVtTVlyaFZKdTFqY0ZXVjdmei9yKzIxL2F3VG5EVjlzTVlRcXVJUllZeTdiRzByMU9iaXdkb3ZudGsKN2dGSTA2WjB2WmFjREU1Ym9xVUNBd0VBQWFPQ0FTVXdnZ0VoTUFrR0ExVWRFd1FDTUFBd0N3WURWUjBQQkFRRApBZ1VnTUIwR0ExVWREZ1FXQkJTUk9OOEdKOG8rOGpnRnRqa3R3WmRxeDZCUnlUQVRCZ05WSFNVRUREQUtCZ2dyCkJnRUZCUWNEQVRBZEJnbGdoa2dCaHZoQ0FRMEVFQllPVkdWemRDQllOVEE1SUdObGNuUXdnYk1HQTFVZEl3U0IKcXpDQnFJQVVrVGpmQmlmS1B2STRCYlk1TGNHWGFzZWdVY21oZ1l5a2dZa3dnWVl4Q3pBSkJnTlZCQVlUQWtGVgpNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVEJsTjVaRzVsZVRFTU1Bb0dBMVVFQ2d3RFVFbFVNUWt3CkJ3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psYm1ObGNHbDBMbU52YlRFbE1DTUdDU3FHU0liM0RRRUoKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnZiWUlCQVRBTkJna3Foa2lHOXcwQkFRc0ZBQU9CZ1FDRQpUQWVKVERTQVc2ejFVRlRWN1FyZWg0VUxGT1JhajkrZUN1RjNLV0RIYyswSVFDajlyZG5ERzRRL3dmNy9yYVEwCkpuUFFDU0NkclBMSmV5b1BIN1FhVHdvYUY3ZHpWdzRMQ3N5TkpURld4NGNNNTBWdzZSNWZET2dpQzhic2ZmUzgKQkptb3VscnJaRE5OVmpHOG1XNmNMeHJZdlZRT3JSVmVjQ0ZJZ3NzQ2JBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=</ds:X509Certificate>
|
15
|
+
</ds:X509Data>
|
16
|
+
</ds:KeyInfo>
|
17
|
+
</md:KeyDescriptor>
|
18
|
+
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://sp.example.com/saml2-logout.php/default-sp"/>
|
19
|
+
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sp.example.com/saml2-acs.php/default-sp" index="0"/>
|
20
|
+
</md:SPSSODescriptor>
|
21
|
+
</md:EntityDescriptor>
|
data/test/response_test.rb
CHANGED
@@ -30,6 +30,7 @@ class RubySamlTest < Minitest::Test
|
|
30
30
|
let(:response_no_statuscode) { OneLogin::RubySaml::Response.new(read_invalid_response("no_status_code.xml.base64")) }
|
31
31
|
let(:response_statuscode_responder) { OneLogin::RubySaml::Response.new(read_invalid_response("status_code_responder.xml.base64")) }
|
32
32
|
let(:response_statuscode_responder_and_msg) { OneLogin::RubySaml::Response.new(read_invalid_response("status_code_responer_and_msg.xml.base64")) }
|
33
|
+
let(:response_double_statuscode) { OneLogin::RubySaml::Response.new(response_document_double_status_code) }
|
33
34
|
let(:response_encrypted_attrs) { OneLogin::RubySaml::Response.new(response_document_encrypted_attrs) }
|
34
35
|
let(:response_no_signed_elements) { OneLogin::RubySaml::Response.new(read_invalid_response("no_signature.xml.base64")) }
|
35
36
|
let(:response_multiple_signed) { OneLogin::RubySaml::Response.new(read_invalid_response("multiple_signed.xml.base64")) }
|
@@ -138,6 +139,7 @@ class RubySamlTest < Minitest::Test
|
|
138
139
|
it "raise when No fingerprint or certificate on settings" do
|
139
140
|
settings.idp_cert_fingerprint = nil
|
140
141
|
settings.idp_cert = nil
|
142
|
+
settings.idp_cert_multi = nil
|
141
143
|
response.settings = settings
|
142
144
|
error_msg = "No fingerprint or certificate on settings"
|
143
145
|
assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
|
@@ -516,12 +518,12 @@ class RubySamlTest < Minitest::Test
|
|
516
518
|
assert_empty response.errors
|
517
519
|
end
|
518
520
|
|
519
|
-
it "return false when
|
521
|
+
it "return false when no Status provided" do
|
520
522
|
assert !response_no_status.send(:validate_success_status)
|
521
523
|
assert_includes response_no_status.errors, "The status code of the Response was not Success"
|
522
524
|
end
|
523
525
|
|
524
|
-
it "return false when
|
526
|
+
it "return false when no StatusCode provided" do
|
525
527
|
assert !response_no_statuscode.send(:validate_success_status)
|
526
528
|
assert_includes response_no_statuscode.errors, "The status code of the Response was not Success"
|
527
529
|
end
|
@@ -535,6 +537,11 @@ class RubySamlTest < Minitest::Test
|
|
535
537
|
assert !response_statuscode_responder_and_msg.send(:validate_success_status)
|
536
538
|
assert_includes response_statuscode_responder_and_msg.errors, "The status code of the Response was not Success, was Responder -> something_is_wrong"
|
537
539
|
end
|
540
|
+
|
541
|
+
it "return false when the status is not 'Success'" do
|
542
|
+
assert !response_double_statuscode.send(:validate_success_status)
|
543
|
+
assert_includes response_double_statuscode.errors, "The status code of the Response was not Success, was Requester => UnsupportedBinding"
|
544
|
+
end
|
538
545
|
end
|
539
546
|
|
540
547
|
describe "#validate_structure" do
|
@@ -1271,6 +1278,11 @@ class RubySamlTest < Minitest::Test
|
|
1271
1278
|
|
1272
1279
|
response4 = OneLogin::RubySaml::Response.new(unsigned_message_encrypted_unsigned_assertion, :settings => settings)
|
1273
1280
|
assert response4.decrypted_document
|
1281
|
+
|
1282
|
+
assert OneLogin::RubySaml::Response.new(
|
1283
|
+
Base64.encode64(File.read('test/responses/unsigned_encrypted_adfs.xml')),
|
1284
|
+
:settings => settings
|
1285
|
+
).decrypted_document
|
1274
1286
|
end
|
1275
1287
|
end
|
1276
1288
|
|
@@ -0,0 +1 @@
|
|
1
|
+
PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgSUQ9InBmeGJjODI2YWZkLWU5ZmUtZDNmYi1kODc0LWM0NzAwYzNlZjBjOCIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMDYtMDRUMDI6MjI6MDJaIiBEZXN0aW5hdGlvbj0iaHR0cDovL2FwcC5tdWRhLm5vL3Nzby9jb25zdW1lIiBJblJlc3BvbnNlVG89Il9mYzRhMzRiMC03ZWZiLTAxMmUtY2FhZS03ODJiY2IxM2JiMzgiPjxzYW1sOklzc3Vlcj5odHRwczovL2FwcC5vbmVsb2dpbi5jb20vc2FtbDI8L3NhbWw6SXNzdWVyPjxzYW1scDpTdGF0dXM+PHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6UmVxdWVzdGVyIj4gIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlVuc3VwcG9ydGVkQmluZGluZyIgLz48L3NhbWxwOlN0YXR1c0NvZGU+PC9zYW1scDpTdGF0dXM+PHNhbWw6QXNzZXJ0aW9uIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgVmVyc2lvbj0iMi4wIiBJRD0icGZ4OTUxNmIwZjMtNDUzNi0xMGY2LWM2ZmEtOWRkNTIzZTE0OThjIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMDYtMDRUMDI6MjI6MDJaIj48c2FtbDpJc3N1ZXI+aHR0cHM6Ly9hcHAub25lbG9naW4uY29tL3NhbWwyPC9zYW1sOklzc3Vlcj48c2FtbDpTdWJqZWN0PjxzYW1sOk5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI+dGVzdEBvbmVsb2dpbi5jb208L3NhbWw6TmFtZUlEPjxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjIwOTAtMDYtMDRUMDI6Mjc6MDJaIiBSZWNpcGllbnQ9InJlY2lwaWVudCIvPjwvc2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uPjwvc2FtbDpTdWJqZWN0PjxzYW1sOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDExLTA2LTA0VDAyOjE3OjAyWiIgTm90T25PckFmdGVyPSIyMDkwLTA2LTA0VDAyOjI3OjAyWiI+PHNhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj48c2FtbDpBdWRpZW5jZT5odHRwczovL3NvbWVvbmUuZXhhbXBsZS5jb20vYXVkaWVuY2U8L3NhbWw6QXVkaWVuY2U+PC9zYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+PC9zYW1sOkNvbmRpdGlvbnM+PHNhbWw6QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDE0LTA2LTA0VDAyOjIyOjAyWiIgU2Vzc2lvbk5vdE9uT3JBZnRlcj0iMjA5MC0wNi0wNVQwMjoyMjowMloiIFNlc3Npb25JbmRleD0iXzE2ZjU3MGZiYzAzMTUwMDdhMDM1NWRmZWE2YjNjNDZjIj48c2FtbDpBdXRobkNvbnRleHQ+PHNhbWw6QXV0aG5Db250ZXh0Q2xhc3NSZWY+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFjOmNsYXNzZXM6UGFzc3dvcmRQcm90ZWN0ZWRUcmFuc3BvcnQ8L3NhbWw6QXV0aG5Db250ZXh0Q2xhc3NSZWY+PC9zYW1sOkF1dGhuQ29udGV4dD48L3NhbWw6QXV0aG5TdGF0ZW1lbnQ+PC9zYW1sOkFzc2VydGlvbj48L3NhbWxwOlJlc3BvbnNlPg==
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_9365faa3a6f6a23b5cd75a74cb0786dc19e845200e" Version="2.0" IssueInstant="2015-03-19T14:00:31Z" Destination="http://rubysaml.com:3000/saml/acs" InResponseTo="_3ab7adb0-b06e-0132-5c3b-0090f5dedd77">
|
3
|
+
<saml:Issuer>https://idp.example.com/simplesaml/saml2/idp/metadata.php</saml:Issuer>
|
4
|
+
<samlp:Status>
|
5
|
+
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
|
6
|
+
</samlp:Status>
|
7
|
+
<EncryptedAssertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
|
8
|
+
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
|
9
|
+
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
|
10
|
+
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
11
|
+
<e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#">
|
12
|
+
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
|
13
|
+
<e:CipherData>
|
14
|
+
<e:CipherValue>xkJn7LQHrTZzLdrNec33hMSC5dc8B0uM4fw8HKhwpkWINwC9deaj0QVz4fZ82Zv2QdP3v6r0wJ/8VrUIF8puJTHSU0u2EUU+XqBJxvivGp2UhUPCyWmirSi6efBnWqMKhOz5YJoaLEu17yw+kOnavLZPv2bB8b5bo2mZPiaPG6s=</e:CipherValue>
|
15
|
+
</e:CipherData>
|
16
|
+
</e:EncryptedKey>
|
17
|
+
</KeyInfo>
|
18
|
+
<xenc:CipherData>
|
19
|
+
<xenc:CipherValue>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</xenc:CipherValue>
|
20
|
+
</xenc:CipherData>
|
21
|
+
</xenc:EncryptedData>
|
22
|
+
</EncryptedAssertion>
|
23
|
+
</samlp:Response>
|
data/test/test_helper.rb
CHANGED
@@ -136,6 +136,10 @@ class Minitest::Test
|
|
136
136
|
@response_document_encrypted_attrs ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_encrypted_attrs.xml.base64'))
|
137
137
|
end
|
138
138
|
|
139
|
+
def response_document_double_status_code
|
140
|
+
@response_document_double_status_code ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_double_status_code.xml.base64'))
|
141
|
+
end
|
142
|
+
|
139
143
|
def signature_fingerprint_1
|
140
144
|
@signature_fingerprint1 ||= "C5:19:85:D9:47:F1:BE:57:08:20:25:05:08:46:EB:27:F6:CA:B7:83"
|
141
145
|
end
|
@@ -162,6 +166,10 @@ class Minitest::Test
|
|
162
166
|
@idp_metadata_descriptor3 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_3.xml'))
|
163
167
|
end
|
164
168
|
|
169
|
+
def no_idp_metadata_descriptor
|
170
|
+
@no_idp_metadata_descriptor ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'no_idp_descriptor.xml'))
|
171
|
+
end
|
172
|
+
|
165
173
|
def idp_metadata_multiple_descriptors
|
166
174
|
@idp_metadata_multiple_descriptors ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_multiple_descriptors.xml'))
|
167
175
|
end
|
data/test/xml_security_test.rb
CHANGED
@@ -106,7 +106,7 @@ class XmlSecurityTest < Minitest::Test
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
describe "#algorithm" do
|
109
|
+
describe "#algorithm" do
|
110
110
|
it "SHA1" do
|
111
111
|
alg = OpenSSL::Digest::SHA1
|
112
112
|
assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2000/09/xmldsig#rsa-sha1")
|
@@ -130,7 +130,7 @@ class XmlSecurityTest < Minitest::Test
|
|
130
130
|
alg = OpenSSL::Digest::SHA512
|
131
131
|
assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512")
|
132
132
|
assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2001/04/xmldsig-more#sha512")
|
133
|
-
end
|
133
|
+
end
|
134
134
|
end
|
135
135
|
|
136
136
|
describe "Fingerprint Algorithms" do
|
@@ -278,7 +278,7 @@ class XmlSecurityTest < Minitest::Test
|
|
278
278
|
logout_request2.sign_document(ruby_saml_key, ruby_saml_cert_text)
|
279
279
|
# verify our signature
|
280
280
|
signed_doc2 = XMLSecurity::SignedDocument.new(logout_request2.to_s)
|
281
|
-
signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
|
281
|
+
signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
|
282
282
|
assert signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
|
283
283
|
end
|
284
284
|
|
@@ -293,7 +293,7 @@ class XmlSecurityTest < Minitest::Test
|
|
293
293
|
logout_response2.sign_document(ruby_saml_key, ruby_saml_cert_text)
|
294
294
|
# verify our signature
|
295
295
|
signed_doc2 = XMLSecurity::SignedDocument.new(logout_response2.to_s)
|
296
|
-
signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
|
296
|
+
signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
|
297
297
|
assert signed_doc2.validate_document(ruby_saml_cert_fingerprint, false)
|
298
298
|
end
|
299
299
|
end
|
@@ -316,9 +316,14 @@ class XmlSecurityTest < Minitest::Test
|
|
316
316
|
Timecop.freeze Time.parse('2012-11-20 17:55:00 UTC') do
|
317
317
|
assert !response.is_valid?
|
318
318
|
|
319
|
-
|
320
|
-
|
321
|
-
|
319
|
+
time_1 = '2012-11-20 17:55:00 UTC < 2012-11-28 17:53:45 UTC'
|
320
|
+
time_2 = 'Tue Nov 20 17:55:00 UTC 2012 < Wed Nov 28 17:53:45 UTC 2012'
|
321
|
+
|
322
|
+
errors = [time_1, time_2].map do |time|
|
323
|
+
"Current time is earlier than NotBefore condition (#{time})"
|
324
|
+
end
|
325
|
+
|
326
|
+
assert_predicate response.errors & errors, :any?
|
322
327
|
end
|
323
328
|
end
|
324
329
|
|
@@ -344,7 +349,7 @@ class XmlSecurityTest < Minitest::Test
|
|
344
349
|
assert document.validate_document(fingerprint, true), 'Document should be valid'
|
345
350
|
end
|
346
351
|
end
|
347
|
-
|
352
|
+
|
348
353
|
describe 'when response has signed assertion' do
|
349
354
|
let(:document_data) { read_response('response_with_signed_assertion_3.xml') }
|
350
355
|
let(:document) { OneLogin::RubySaml::Response.new(document_data).document }
|
@@ -388,5 +393,29 @@ class XmlSecurityTest < Minitest::Test
|
|
388
393
|
end
|
389
394
|
end
|
390
395
|
end
|
396
|
+
|
397
|
+
describe '#validate_document_with_cert' do
|
398
|
+
describe 'with valid document ' do
|
399
|
+
describe 'when response has cert' do
|
400
|
+
let(:document_data) { read_response('response_with_signed_message_and_assertion.xml') }
|
401
|
+
let(:document) { OneLogin::RubySaml::Response.new(document_data).document }
|
402
|
+
let(:idp_cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
|
403
|
+
let(:fingerprint) { '4b68c453c7d994aad9025c99d5efcf566287fe8d' }
|
404
|
+
|
405
|
+
it 'is valid' do
|
406
|
+
assert document.validate_document_with_cert(idp_cert), 'Document should be valid'
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
describe 'when response has no cert but you have local cert' do
|
411
|
+
let(:document) { OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate).document }
|
412
|
+
let(:idp_cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
|
413
|
+
|
414
|
+
it 'is valid' do
|
415
|
+
assert document.validate_document_with_cert(idp_cert), 'Document should be valid'
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
391
420
|
end
|
392
421
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-saml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OneLogin LLC
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -218,6 +218,7 @@ files:
|
|
218
218
|
- test/metadata/idp_descriptor_2.xml
|
219
219
|
- test/metadata/idp_descriptor_3.xml
|
220
220
|
- test/metadata/idp_multiple_descriptors.xml
|
221
|
+
- test/metadata/no_idp_descriptor.xml
|
221
222
|
- test/metadata_test.rb
|
222
223
|
- test/request_test.rb
|
223
224
|
- test/response_test.rb
|
@@ -263,6 +264,7 @@ files:
|
|
263
264
|
- test/responses/no_signature_ns.xml
|
264
265
|
- test/responses/open_saml_response.xml
|
265
266
|
- test/responses/response_assertion_wrapped.xml.base64
|
267
|
+
- test/responses/response_double_status_code.xml.base64
|
266
268
|
- test/responses/response_encrypted_attrs.xml.base64
|
267
269
|
- test/responses/response_encrypted_nameid.xml.base64
|
268
270
|
- test/responses/response_eval.xml
|
@@ -290,6 +292,7 @@ files:
|
|
290
292
|
- test/responses/simple_saml_php.xml
|
291
293
|
- test/responses/starfield_response.xml.base64
|
292
294
|
- test/responses/test_sign.xml
|
295
|
+
- test/responses/unsigned_encrypted_adfs.xml
|
293
296
|
- test/responses/unsigned_message_aes128_encrypted_signed_assertion.xml.base64
|
294
297
|
- test/responses/unsigned_message_aes192_encrypted_signed_assertion.xml.base64
|
295
298
|
- test/responses/unsigned_message_aes256_encrypted_signed_assertion.xml.base64
|
@@ -327,7 +330,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
327
330
|
version: '0'
|
328
331
|
requirements: []
|
329
332
|
rubyforge_project: http://www.rubygems.org/gems/ruby-saml
|
330
|
-
rubygems_version: 2.
|
333
|
+
rubygems_version: 2.5.1
|
331
334
|
signing_key:
|
332
335
|
specification_version: 4
|
333
336
|
summary: SAML Ruby Tookit
|
@@ -363,6 +366,7 @@ test_files:
|
|
363
366
|
- test/metadata/idp_descriptor_2.xml
|
364
367
|
- test/metadata/idp_descriptor_3.xml
|
365
368
|
- test/metadata/idp_multiple_descriptors.xml
|
369
|
+
- test/metadata/no_idp_descriptor.xml
|
366
370
|
- test/metadata_test.rb
|
367
371
|
- test/request_test.rb
|
368
372
|
- test/response_test.rb
|
@@ -408,6 +412,7 @@ test_files:
|
|
408
412
|
- test/responses/no_signature_ns.xml
|
409
413
|
- test/responses/open_saml_response.xml
|
410
414
|
- test/responses/response_assertion_wrapped.xml.base64
|
415
|
+
- test/responses/response_double_status_code.xml.base64
|
411
416
|
- test/responses/response_encrypted_attrs.xml.base64
|
412
417
|
- test/responses/response_encrypted_nameid.xml.base64
|
413
418
|
- test/responses/response_eval.xml
|
@@ -435,6 +440,7 @@ test_files:
|
|
435
440
|
- test/responses/simple_saml_php.xml
|
436
441
|
- test/responses/starfield_response.xml.base64
|
437
442
|
- test/responses/test_sign.xml
|
443
|
+
- test/responses/unsigned_encrypted_adfs.xml
|
438
444
|
- test/responses/unsigned_message_aes128_encrypted_signed_assertion.xml.base64
|
439
445
|
- test/responses/unsigned_message_aes192_encrypted_signed_assertion.xml.base64
|
440
446
|
- test/responses/unsigned_message_aes256_encrypted_signed_assertion.xml.base64
|