ruby-saml 1.1.2 → 1.2.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 +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
|
|