ruby-saml 1.4.3 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ruby-saml might be problematic. Click here for more details.
- 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 [![Build Status](https://secure.travis-ci.org/onelogin/ruby-saml.svg)](http://travis-ci.org/onelogin/ruby-saml) [![Coverage Status](https://coveralls.io/repos/onelogin/ruby-saml/badge.svg?branch=master%0A)](https://coveralls.io/r/onelogin/ruby-saml?branch=master%0A) [![Gem Version](https://badge.fury.io/rb/ruby-saml.svg)](http://badge.fury.io/rb/ruby-saml)
|
2
2
|
|
3
|
+
## 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
|