ruby-saml 1.1.2 → 1.2.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 +7 -0
- data/README.md +15 -6
- data/changelog.md +15 -1
- data/lib/onelogin/ruby-saml/authrequest.rb +2 -2
- data/lib/onelogin/ruby-saml/error_handling.rb +27 -0
- data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +80 -16
- data/lib/onelogin/ruby-saml/logoutrequest.rb +3 -4
- data/lib/onelogin/ruby-saml/logoutresponse.rb +20 -22
- data/lib/onelogin/ruby-saml/metadata.rb +3 -4
- data/lib/onelogin/ruby-saml/response.rb +79 -50
- data/lib/onelogin/ruby-saml/saml_message.rb +3 -10
- data/lib/onelogin/ruby-saml/settings.rb +2 -0
- data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +32 -32
- data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +3 -3
- data/lib/onelogin/ruby-saml/utils.rb +25 -9
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/xml_security.rb +29 -27
- data/ruby-saml.gemspec +4 -1
- data/test/idp_metadata_parser_test.rb +28 -0
- data/test/logoutrequest_test.rb +2 -1
- data/test/logoutresponse_test.rb +9 -0
- data/test/metadata_test.rb +14 -0
- data/test/response_test.rb +70 -6
- data/test/responses/idp_descriptor.xml +1 -1
- data/test/responses/response_with_retrieval_method.xml +26 -0
- data/test/responses/response_without_reference_uri.xml.base64 +1 -1
- data/test/settings_test.rb +1 -1
- data/test/slo_logoutrequest_test.rb +29 -2
- data/test/test_helper.rb +1 -1
- data/test/utils_test.rb +14 -1
- data/test/xml_security_test.rb +2 -0
- metadata +133 -177
@@ -5,6 +5,7 @@ require 'nokogiri'
|
|
5
5
|
require 'rexml/document'
|
6
6
|
require 'rexml/xpath'
|
7
7
|
require 'thread'
|
8
|
+
require "onelogin/ruby-saml/error_handling"
|
8
9
|
|
9
10
|
# Only supports SAML 2.0
|
10
11
|
module OneLogin
|
@@ -69,23 +70,15 @@ module OneLogin
|
|
69
70
|
end
|
70
71
|
rescue Exception => error
|
71
72
|
return false if soft
|
72
|
-
|
73
|
+
raise ValidationError.new("XML load failed: #{error.message}")
|
73
74
|
end
|
74
75
|
|
75
76
|
SamlMessage.schema.validate(xml).map do |error|
|
76
77
|
return false if soft
|
77
|
-
|
78
|
+
raise ValidationError.new("#{error.message}\n\n#{xml.to_s}")
|
78
79
|
end
|
79
80
|
end
|
80
81
|
|
81
|
-
# Raise a ValidationError with the provided message
|
82
|
-
# @param message [String] Message of the exception
|
83
|
-
# @raise [ValidationError]
|
84
|
-
#
|
85
|
-
def validation_error(message)
|
86
|
-
raise ValidationError.new(message)
|
87
|
-
end
|
88
|
-
|
89
82
|
private
|
90
83
|
|
91
84
|
# Base64 decode and try also to inflate a SAML Message
|
@@ -28,6 +28,7 @@ module OneLogin
|
|
28
28
|
attr_accessor :idp_cert
|
29
29
|
attr_accessor :idp_cert_fingerprint
|
30
30
|
attr_accessor :idp_cert_fingerprint_algorithm
|
31
|
+
attr_accessor :idp_attribute_names
|
31
32
|
# SP Data
|
32
33
|
attr_accessor :issuer
|
33
34
|
attr_accessor :assertion_consumer_service_url
|
@@ -153,6 +154,7 @@ module OneLogin
|
|
153
154
|
:authn_requests_signed => false,
|
154
155
|
:logout_requests_signed => false,
|
155
156
|
:logout_responses_signed => false,
|
157
|
+
:want_assertions_signed => false,
|
156
158
|
:metadata_signed => false,
|
157
159
|
:embed_sign => false,
|
158
160
|
:digest_method => XMLSecurity::Document::SHA1,
|
@@ -11,13 +11,11 @@ module OneLogin
|
|
11
11
|
# SAML2 Logout Request (SLO IdP initiated, Parser)
|
12
12
|
#
|
13
13
|
class SloLogoutrequest < SamlMessage
|
14
|
+
include ErrorHandling
|
14
15
|
|
15
16
|
# OneLogin::RubySaml::Settings Toolkit settings
|
16
17
|
attr_accessor :settings
|
17
18
|
|
18
|
-
# Array with the causes [Array of strings]
|
19
|
-
attr_accessor :errors
|
20
|
-
|
21
19
|
attr_reader :document
|
22
20
|
attr_reader :request
|
23
21
|
attr_reader :options
|
@@ -32,15 +30,15 @@ module OneLogin
|
|
32
30
|
# @raise [ArgumentError] If Request is nil
|
33
31
|
#
|
34
32
|
def initialize(request, options = {})
|
35
|
-
@errors = []
|
36
33
|
raise ArgumentError.new("Request cannot be nil") if request.nil?
|
37
|
-
@options = options
|
38
34
|
|
35
|
+
@errors = []
|
36
|
+
@options = options
|
39
37
|
@soft = true
|
40
|
-
|
38
|
+
unless options[:settings].nil?
|
41
39
|
@settings = options[:settings]
|
42
|
-
|
43
|
-
@soft =
|
40
|
+
unless @settings.soft.nil?
|
41
|
+
@soft = @settings.soft
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
@@ -48,23 +46,12 @@ module OneLogin
|
|
48
46
|
@document = REXML::Document.new(@request)
|
49
47
|
end
|
50
48
|
|
51
|
-
# Append the cause to the errors array, and based on the value of soft, return false or raise
|
52
|
-
# an exception
|
53
|
-
def append_error(error_msg)
|
54
|
-
@errors << error_msg
|
55
|
-
return soft ? false : validation_error(error_msg)
|
56
|
-
end
|
57
|
-
|
58
|
-
# Reset the errors array
|
59
|
-
def reset_errors!
|
60
|
-
@errors = []
|
61
|
-
end
|
62
|
-
|
63
49
|
# Validates the Logout Request with the default values (soft = true)
|
50
|
+
# @param collect_errors [Boolean] Stop validation when first error appears or keep validating.
|
64
51
|
# @return [Boolean] TRUE if the Logout Request is valid
|
65
52
|
#
|
66
|
-
def is_valid?
|
67
|
-
validate
|
53
|
+
def is_valid?(collect_errors = false)
|
54
|
+
validate(collect_errors)
|
68
55
|
end
|
69
56
|
|
70
57
|
# @return [String] Gets the NameID of the Logout Request.
|
@@ -132,19 +119,32 @@ module OneLogin
|
|
132
119
|
private
|
133
120
|
|
134
121
|
# Hard aux function to validate the Logout Request
|
122
|
+
# @param collect_errors [Boolean] Stop validation when first error appears or keep validating. (if soft=true)
|
135
123
|
# @return [Boolean] TRUE if the Logout Request is valid
|
136
124
|
# @raise [ValidationError] if soft == false and validation fails
|
137
125
|
#
|
138
|
-
def validate
|
126
|
+
def validate(collect_errors = false)
|
139
127
|
reset_errors!
|
140
128
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
129
|
+
if collect_errors
|
130
|
+
validate_request_state
|
131
|
+
validate_id
|
132
|
+
validate_version
|
133
|
+
validate_structure
|
134
|
+
validate_not_on_or_after
|
135
|
+
validate_issuer
|
136
|
+
validate_signature
|
137
|
+
|
138
|
+
@errors.empty?
|
139
|
+
else
|
140
|
+
validate_request_state &&
|
141
|
+
validate_id &&
|
142
|
+
validate_version &&
|
143
|
+
validate_structure &&
|
144
|
+
validate_not_on_or_after &&
|
145
|
+
validate_issuer &&
|
146
|
+
validate_signature
|
147
|
+
end
|
148
148
|
end
|
149
149
|
|
150
150
|
# Validates that the Logout Request contains an ID
|
@@ -213,7 +213,7 @@ module OneLogin
|
|
213
213
|
# @raise [ValidationError] if soft == false and validation fails
|
214
214
|
#
|
215
215
|
def validate_issuer
|
216
|
-
return true if settings.idp_entity_id.nil? || issuer.nil?
|
216
|
+
return true if settings.nil? || settings.idp_entity_id.nil? || issuer.nil?
|
217
217
|
|
218
218
|
unless URI.parse(issuer) == URI.parse(settings.idp_entity_id)
|
219
219
|
return append_error("Doesn't match the issuer, expected: <#{settings.idp_entity_id}>, but was: <#{issuer}>")
|
@@ -230,7 +230,7 @@ module OneLogin
|
|
230
230
|
return true if options.nil?
|
231
231
|
return true unless options.has_key? :get_params
|
232
232
|
return true unless options[:get_params].has_key? 'Signature'
|
233
|
-
return true if settings.
|
233
|
+
return true if settings.get_idp_cert.nil?
|
234
234
|
|
235
235
|
query_string = OneLogin::RubySaml::Utils.build_query(
|
236
236
|
:type => 'SAMLRequest',
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require "uuid"
|
2
|
-
|
3
1
|
require "onelogin/ruby-saml/logging"
|
2
|
+
|
4
3
|
require "onelogin/ruby-saml/saml_message"
|
4
|
+
require "onelogin/ruby-saml/utils"
|
5
5
|
|
6
6
|
# Only supports SAML 2.0
|
7
7
|
module OneLogin
|
@@ -18,7 +18,7 @@ module OneLogin
|
|
18
18
|
# Asigns an ID, a random uuid.
|
19
19
|
#
|
20
20
|
def initialize
|
21
|
-
@uuid =
|
21
|
+
@uuid = OneLogin::RubySaml::Utils.uuid
|
22
22
|
end
|
23
23
|
|
24
24
|
# Creates the Logout Response string.
|
@@ -1,9 +1,16 @@
|
|
1
|
+
if RUBY_VERSION < '1.9'
|
2
|
+
require 'uuid'
|
3
|
+
else
|
4
|
+
require 'securerandom'
|
5
|
+
end
|
6
|
+
|
1
7
|
module OneLogin
|
2
8
|
module RubySaml
|
3
9
|
|
4
10
|
# SAML2 Auxiliary class
|
5
|
-
#
|
11
|
+
#
|
6
12
|
class Utils
|
13
|
+
@@uuid_generator = UUID.new if RUBY_VERSION < '1.9'
|
7
14
|
|
8
15
|
DSIG = "http://www.w3.org/2000/09/xmldsig#"
|
9
16
|
XENC = "http://www.w3.org/2001/04/xmlenc#"
|
@@ -30,7 +37,7 @@ module OneLogin
|
|
30
37
|
# @return [String] The formatted private key
|
31
38
|
#
|
32
39
|
def self.format_private_key(key)
|
33
|
-
# don't try to format an encoded private key or if is empty
|
40
|
+
# don't try to format an encoded private key or if is empty
|
34
41
|
return key if key.nil? || key.empty? || key.match(/\x0d/)
|
35
42
|
|
36
43
|
# is this an rsa key?
|
@@ -114,7 +121,7 @@ module OneLogin
|
|
114
121
|
{ 'xenc' => XENC }
|
115
122
|
)
|
116
123
|
algorithm = encrypt_method.attributes['Algorithm']
|
117
|
-
retrieve_plaintext(node, symmetric_key, algorithm)
|
124
|
+
retrieve_plaintext(node, symmetric_key, algorithm)
|
118
125
|
end
|
119
126
|
|
120
127
|
# Obtains the symmetric key from the EncryptedData element
|
@@ -122,19 +129,25 @@ module OneLogin
|
|
122
129
|
# @param private_key [OpenSSL::PKey::RSA] The Service provider private key
|
123
130
|
# @return [String] The symmetric key
|
124
131
|
def self.retrieve_symmetric_key(encrypt_data, private_key)
|
125
|
-
|
132
|
+
encrypted_key = REXML::XPath.first(
|
126
133
|
encrypt_data,
|
127
|
-
"//xenc:EncryptedData/ds:KeyInfo/xenc:EncryptedKey
|
134
|
+
"//xenc:EncryptedData/ds:KeyInfo/xenc:EncryptedKey or \
|
135
|
+
//xenc:EncryptedKey[@Id=substring-after(//xenc:EncryptedData/ds:KeyInfo/ds:RetrievalMethod/@URI, '#')]",
|
136
|
+
{ "ds" => DSIG, "xenc" => XENC }
|
137
|
+
)
|
138
|
+
encrypted_symmetric_key_element = REXML::XPath.first(
|
139
|
+
encrypted_key,
|
140
|
+
"./xenc:CipherData/xenc:CipherValue",
|
128
141
|
{ "ds" => DSIG, "xenc" => XENC }
|
129
142
|
)
|
130
143
|
cipher_text = Base64.decode64(encrypted_symmetric_key_element.text)
|
131
144
|
encrypt_method = REXML::XPath.first(
|
132
|
-
|
133
|
-
"
|
145
|
+
encrypted_key,
|
146
|
+
"./xenc:EncryptionMethod",
|
134
147
|
{"ds" => DSIG, "xenc" => XENC }
|
135
148
|
)
|
136
149
|
algorithm = encrypt_method.attributes['Algorithm']
|
137
|
-
retrieve_plaintext(cipher_text, private_key, algorithm)
|
150
|
+
retrieve_plaintext(cipher_text, private_key, algorithm)
|
138
151
|
end
|
139
152
|
|
140
153
|
# Obtains the deciphered text
|
@@ -152,7 +165,7 @@ module OneLogin
|
|
152
165
|
when 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' then oaep = symmetric_key
|
153
166
|
end
|
154
167
|
|
155
|
-
if cipher
|
168
|
+
if cipher
|
156
169
|
iv_len = cipher.iv_len
|
157
170
|
data = cipher_text[iv_len..-1]
|
158
171
|
cipher.padding, cipher.key, cipher.iv = 0, symmetric_key, cipher_text[0..iv_len-1]
|
@@ -167,6 +180,9 @@ module OneLogin
|
|
167
180
|
end
|
168
181
|
end
|
169
182
|
|
183
|
+
def self.uuid
|
184
|
+
RUBY_VERSION < '1.9' ? "_#{@@uuid_generator.generate}" : "_#{SecureRandom.uuid}"
|
185
|
+
end
|
170
186
|
end
|
171
187
|
end
|
172
188
|
end
|
data/lib/xml_security.rb
CHANGED
@@ -29,7 +29,7 @@ require "openssl"
|
|
29
29
|
require 'nokogiri'
|
30
30
|
require "digest/sha1"
|
31
31
|
require "digest/sha2"
|
32
|
-
require "onelogin/ruby-saml/
|
32
|
+
require "onelogin/ruby-saml/error_handling"
|
33
33
|
|
34
34
|
module XMLSecurity
|
35
35
|
|
@@ -48,9 +48,14 @@ module XMLSecurity
|
|
48
48
|
end
|
49
49
|
|
50
50
|
case algorithm
|
51
|
-
when "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
|
52
|
-
|
53
|
-
|
51
|
+
when "http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
|
52
|
+
"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"
|
53
|
+
Nokogiri::XML::XML_C14N_1_0
|
54
|
+
when "http://www.w3.org/2006/12/xml-c14n11",
|
55
|
+
"http://www.w3.org/2006/12/xml-c14n11#WithComments"
|
56
|
+
Nokogiri::XML::XML_C14N_1_1
|
57
|
+
else
|
58
|
+
Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
|
54
59
|
end
|
55
60
|
end
|
56
61
|
|
@@ -74,10 +79,10 @@ module XMLSecurity
|
|
74
79
|
end
|
75
80
|
|
76
81
|
class Document < BaseDocument
|
77
|
-
RSA_SHA1
|
78
|
-
RSA_SHA256
|
79
|
-
RSA_SHA384
|
80
|
-
RSA_SHA512
|
82
|
+
RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
|
83
|
+
RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
|
84
|
+
RSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"
|
85
|
+
RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"
|
81
86
|
SHA1 = "http://www.w3.org/2000/09/xmldsig#sha1"
|
82
87
|
SHA256 = "http://www.w3.org/2001/04/xmldsig-more#sha256"
|
83
88
|
SHA384 = "http://www.w3.org/2001/04/xmldsig-more#sha384"
|
@@ -179,9 +184,9 @@ module XMLSecurity
|
|
179
184
|
end
|
180
185
|
|
181
186
|
class SignedDocument < BaseDocument
|
187
|
+
include OneLogin::RubySaml::ErrorHandling
|
182
188
|
|
183
189
|
attr_accessor :signed_element_id
|
184
|
-
attr_accessor :errors
|
185
190
|
|
186
191
|
def initialize(response, errors = [])
|
187
192
|
super(response)
|
@@ -200,10 +205,14 @@ module XMLSecurity
|
|
200
205
|
{ "ds"=>DSIG }
|
201
206
|
)
|
202
207
|
|
203
|
-
if cert_element
|
208
|
+
if cert_element
|
204
209
|
base64_cert = cert_element.text
|
205
210
|
cert_text = Base64.decode64(base64_cert)
|
206
|
-
|
211
|
+
begin
|
212
|
+
cert = OpenSSL::X509::Certificate.new(cert_text)
|
213
|
+
rescue OpenSSL::X509::CertificateError => e
|
214
|
+
return append_error("Certificate Error", soft)
|
215
|
+
end
|
207
216
|
|
208
217
|
if options[:fingerprint_alg]
|
209
218
|
fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(options[:fingerprint_alg]).new
|
@@ -215,7 +224,7 @@ module XMLSecurity
|
|
215
224
|
# check cert matches registered idp cert
|
216
225
|
if fingerprint != idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/,"").downcase
|
217
226
|
@errors << "Fingerprint mismatch"
|
218
|
-
return
|
227
|
+
return append_error("Fingerprint mismatch", soft)
|
219
228
|
end
|
220
229
|
else
|
221
230
|
if options[:cert]
|
@@ -224,8 +233,8 @@ module XMLSecurity
|
|
224
233
|
if soft
|
225
234
|
return false
|
226
235
|
else
|
227
|
-
|
228
|
-
end
|
236
|
+
return append_error("Certificate element missing in response (ds:X509Certificate) and not cert provided at settings", soft)
|
237
|
+
end
|
229
238
|
end
|
230
239
|
end
|
231
240
|
validate_signature(base64_cert, soft)
|
@@ -273,12 +282,6 @@ module XMLSecurity
|
|
273
282
|
noko_sig_element = document.at_xpath('//ds:Signature', 'ds' => DSIG)
|
274
283
|
noko_signed_info_element = noko_sig_element.at_xpath('./ds:SignedInfo', 'ds' => DSIG)
|
275
284
|
|
276
|
-
# Handle when no URI
|
277
|
-
noko_signed_info_reference_element_uri_attr = noko_signed_info_element.at_xpath('./ds:Reference', 'ds' => DSIG).attributes["URI"]
|
278
|
-
if (noko_signed_info_reference_element_uri_attr.value.empty?)
|
279
|
-
noko_signed_info_reference_element_uri_attr.value = "##{document.root.attribute('ID')}"
|
280
|
-
end
|
281
|
-
|
282
285
|
canon_string = noko_signed_info_element.canonicalize(canon_algorithm)
|
283
286
|
noko_sig_element.remove
|
284
287
|
|
@@ -289,8 +292,8 @@ module XMLSecurity
|
|
289
292
|
ref = REXML::XPath.first(sig_element, "//ds:Reference", {"ds"=>DSIG})
|
290
293
|
uri = ref.attributes.get_attribute("URI").value
|
291
294
|
|
292
|
-
hashed_element =
|
293
|
-
|
295
|
+
hashed_element = document.at_xpath("//*[@ID=$id]", nil, { 'id' => extract_signed_element_id })
|
296
|
+
|
294
297
|
canon_algorithm = canon_algorithm REXML::XPath.first(
|
295
298
|
ref,
|
296
299
|
'//ds:CanonicalizationMethod',
|
@@ -313,7 +316,7 @@ module XMLSecurity
|
|
313
316
|
|
314
317
|
unless digests_match?(hash, digest_value)
|
315
318
|
@errors << "Digest mismatch"
|
316
|
-
return
|
319
|
+
return append_error("Digest mismatch", soft)
|
317
320
|
end
|
318
321
|
|
319
322
|
# get certificate object
|
@@ -322,8 +325,7 @@ module XMLSecurity
|
|
322
325
|
|
323
326
|
# verify signature
|
324
327
|
unless cert.public_key.verify(signature_algorithm.new, signature, canon_string)
|
325
|
-
|
326
|
-
return soft ? false : (raise OneLogin::RubySaml::ValidationError.new("Key validation error"))
|
328
|
+
return append_error("Key validation error", soft)
|
327
329
|
end
|
328
330
|
|
329
331
|
return true
|
@@ -344,8 +346,8 @@ module XMLSecurity
|
|
344
346
|
|
345
347
|
return nil if reference_element.nil?
|
346
348
|
|
347
|
-
sei = reference_element.attribute("URI").value[1..-1]
|
348
|
-
sei.nil? ?
|
349
|
+
sei = reference_element.attribute("URI").value[1..-1]
|
350
|
+
sei.nil? ? reference_element.parent.parent.parent.attribute("ID").value : sei
|
349
351
|
end
|
350
352
|
|
351
353
|
def extract_inclusive_namespaces
|
data/ruby-saml.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.summary = %q{SAML Ruby Tookit}
|
26
26
|
s.test_files = `git ls-files test/*`.split("\n")
|
27
27
|
|
28
|
-
|
28
|
+
|
29
29
|
|
30
30
|
# Because runtime dependencies are determined at build time, we cannot make
|
31
31
|
# Nokogiri's version dependent on the Ruby version, even though we would
|
@@ -33,6 +33,9 @@ Gem::Specification.new do |s|
|
|
33
33
|
if defined?(JRUBY_VERSION)
|
34
34
|
s.add_runtime_dependency('nokogiri', '>= 1.6.0')
|
35
35
|
s.add_runtime_dependency('jruby-openssl', '>= 0.9.8')
|
36
|
+
elsif RUBY_VERSION < '1.9'
|
37
|
+
s.add_runtime_dependency('uuid')
|
38
|
+
s.add_runtime_dependency('nokogiri', '<= 1.5.11')
|
36
39
|
else
|
37
40
|
s.add_runtime_dependency('nokogiri', '>= 1.5.10')
|
38
41
|
end
|
@@ -28,7 +28,34 @@ class IdpMetadataParserTest < Minitest::Test
|
|
28
28
|
assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint
|
29
29
|
assert_equal "https://example.hello.com/access/saml/logout", settings.idp_slo_target_url
|
30
30
|
assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", settings.name_identifier_format
|
31
|
+
assert_equal ["AuthToken", "SSOStartPage"], settings.idp_attribute_names
|
32
|
+
assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint
|
31
33
|
end
|
34
|
+
|
35
|
+
it "extract certificate from md:KeyDescriptor[@use='signing']" do
|
36
|
+
idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
|
37
|
+
idp_metadata = read_response("idp_descriptor.xml")
|
38
|
+
settings = idp_metadata_parser.parse(idp_metadata)
|
39
|
+
assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint
|
40
|
+
end
|
41
|
+
|
42
|
+
it "extract certificate from md:KeyDescriptor[@use='encryption']" do
|
43
|
+
idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
|
44
|
+
idp_metadata = read_response("idp_descriptor.xml")
|
45
|
+
idp_metadata = idp_metadata.sub(/<md:KeyDescriptor use="signing">(.*?)<\/md:KeyDescriptor>/m, "")
|
46
|
+
settings = idp_metadata_parser.parse(idp_metadata)
|
47
|
+
assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint
|
48
|
+
end
|
49
|
+
|
50
|
+
it "extract certificate from md:KeyDescriptor" do
|
51
|
+
idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
|
52
|
+
idp_metadata = read_response("idp_descriptor.xml")
|
53
|
+
idp_metadata = idp_metadata.sub(/<md:KeyDescriptor use="signing">(.*?)<\/md:KeyDescriptor>/m, "")
|
54
|
+
idp_metadata = idp_metadata.sub('<md:KeyDescriptor use="encryption">', '<md:KeyDescriptor>')
|
55
|
+
settings = idp_metadata_parser.parse(idp_metadata)
|
56
|
+
assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint
|
57
|
+
end
|
58
|
+
|
32
59
|
end
|
33
60
|
|
34
61
|
describe "download and parse IdP descriptor file" do
|
@@ -52,6 +79,7 @@ class IdpMetadataParserTest < Minitest::Test
|
|
52
79
|
assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint
|
53
80
|
assert_equal "https://example.hello.com/access/saml/logout", settings.idp_slo_target_url
|
54
81
|
assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", settings.name_identifier_format
|
82
|
+
assert_equal ["AuthToken", "SSOStartPage"], settings.idp_attribute_names
|
55
83
|
assert_equal OpenSSL::SSL::VERIFY_PEER, @http.verify_mode
|
56
84
|
end
|
57
85
|
|