ruby-saml 0.8.10 → 0.8.15
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/Gemfile +3 -1
- data/Rakefile +0 -14
- data/lib/onelogin/ruby-saml/authrequest.rb +3 -2
- data/lib/onelogin/ruby-saml/logoutrequest.rb +3 -0
- data/lib/onelogin/ruby-saml/logoutresponse.rb +1 -24
- data/lib/onelogin/ruby-saml/response.rb +206 -20
- data/lib/onelogin/ruby-saml/setting_error.rb +6 -0
- data/lib/onelogin/ruby-saml/settings.rb +26 -0
- data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +3 -2
- data/lib/onelogin/ruby-saml/utils.rb +90 -0
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/xml_security.rb +222 -87
- data/test/certificates/ruby-saml-2.crt +15 -0
- data/test/logoutrequest_test.rb +124 -126
- data/test/logoutresponse_test.rb +22 -28
- data/test/response_test.rb +348 -129
- data/test/responses/adfs_response_xmlns.xml +45 -0
- data/test/responses/encrypted_new_attack.xml.base64 +1 -0
- data/test/responses/invalids/multiple_signed.xml.base64 +1 -0
- data/test/responses/invalids/no_signature.xml.base64 +1 -0
- data/test/responses/invalids/response_with_concealed_signed_assertion.xml +51 -0
- data/test/responses/invalids/response_with_doubled_signed_assertion.xml +49 -0
- data/test/responses/invalids/signature_wrapping_attack.xml.base64 +1 -0
- data/test/responses/response_with_concealed_signed_assertion.xml +51 -0
- data/test/responses/response_with_doubled_signed_assertion.xml +49 -0
- data/test/responses/response_with_signed_assertion_3.xml +30 -0
- data/test/responses/response_with_signed_message_and_assertion.xml +34 -0
- data/test/responses/response_with_undefined_recipient.xml.base64 +1 -0
- data/test/responses/response_wrapped.xml.base64 +150 -0
- data/test/responses/valid_response.xml.base64 +1 -0
- data/test/responses/valid_response_without_x509certificate.xml.base64 +1 -0
- data/test/settings_test.rb +5 -5
- data/test/test_helper.rb +110 -41
- data/test/utils_test.rb +10 -10
- data/test/xml_security_test.rb +359 -68
- metadata +38 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3039afb4b2668c3859e51ae9eff0c1b423d7dda319a7d646b26702de315047af
|
4
|
+
data.tar.gz: 2ef188024bd8030c659b499db22b3b28f2ae24930954f8c45cc69c175b8fc4e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ab896476c0de2ebcd71b060dc305d091e3b6c3be7abd81ce702389cb8e8409cbd5730a4a73a71dfdfedbeb7a0081f448ed4aec60737a8ce6c1b6fb966ce9c4f
|
7
|
+
data.tar.gz: 203b1fd9b1fa4d23ab66cac8a034d3154a48e243bff21040ae2e873d191e90c0d8b8ccdfee368ca542c306fd58ddcdbeec700047893ae6044b82b406af43de18
|
data/Gemfile
CHANGED
@@ -7,10 +7,13 @@ gemspec
|
|
7
7
|
|
8
8
|
if RUBY_VERSION < '1.9'
|
9
9
|
gem 'nokogiri', '~> 1.5.0'
|
10
|
+
gem 'minitest', '~> 5.5', '<= 5.11.3'
|
10
11
|
elsif RUBY_VERSION < '2.1'
|
11
12
|
gem 'nokogiri', '>= 1.5.0', '<= 1.6.8.1'
|
13
|
+
gem 'minitest', '~> 5.5'
|
12
14
|
else
|
13
15
|
gem 'nokogiri', '>= 1.5.0'
|
16
|
+
gem 'minitest', '~> 5.5'
|
14
17
|
end
|
15
18
|
|
16
19
|
group :test do
|
@@ -30,6 +33,5 @@ group :test do
|
|
30
33
|
gem 'shoulda', '~> 2.11'
|
31
34
|
gem 'systemu', '~> 2'
|
32
35
|
gem 'test-unit', '~> 3.0.9'
|
33
|
-
gem 'minitest', '~> 5.5'
|
34
36
|
gem 'timecop', '<= 0.6.0'
|
35
37
|
end
|
data/Rakefile
CHANGED
@@ -25,17 +25,3 @@ end
|
|
25
25
|
task :test
|
26
26
|
|
27
27
|
task :default => :test
|
28
|
-
|
29
|
-
# require 'rake/rdoctask'
|
30
|
-
# Rake::RDocTask.new do |rdoc|
|
31
|
-
# if File.exist?('VERSION')
|
32
|
-
# version = File.read('VERSION')
|
33
|
-
# else
|
34
|
-
# version = ""
|
35
|
-
# end
|
36
|
-
|
37
|
-
# rdoc.rdoc_dir = 'rdoc'
|
38
|
-
# rdoc.title = "ruby-saml #{version}"
|
39
|
-
# rdoc.rdoc_files.include('README*')
|
40
|
-
# rdoc.rdoc_files.include('lib/**/*.rb')
|
41
|
-
#end
|
@@ -2,6 +2,7 @@ require "base64"
|
|
2
2
|
require "zlib"
|
3
3
|
require "cgi"
|
4
4
|
require "onelogin/ruby-saml/utils"
|
5
|
+
require "onelogin/ruby-saml/setting_error"
|
5
6
|
|
6
7
|
module OneLogin
|
7
8
|
module RubySaml
|
@@ -25,7 +26,7 @@ module OneLogin
|
|
25
26
|
params.each_pair do |key, value|
|
26
27
|
request_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
|
27
28
|
end
|
28
|
-
raise "Invalid settings, idp_sso_target_url is not set!" if settings.idp_sso_target_url.nil?
|
29
|
+
raise SettingError.new "Invalid settings, idp_sso_target_url is not set!" if settings.idp_sso_target_url.nil? or settings.idp_sso_target_url.empty?
|
29
30
|
@login_url = settings.idp_sso_target_url + request_params
|
30
31
|
end
|
31
32
|
|
@@ -101,7 +102,7 @@ module OneLogin
|
|
101
102
|
root.attributes['ID'] = uuid
|
102
103
|
root.attributes['IssueInstant'] = time
|
103
104
|
root.attributes['Version'] = "2.0"
|
104
|
-
root.attributes['Destination'] = settings.idp_sso_target_url unless settings.idp_sso_target_url.nil?
|
105
|
+
root.attributes['Destination'] = settings.idp_sso_target_url unless settings.idp_sso_target_url.nil? or settings.idp_sso_target_url.empty?
|
105
106
|
root.attributes['IsPassive'] = settings.passive unless settings.passive.nil?
|
106
107
|
root.attributes['ProtocolBinding'] = settings.protocol_binding unless settings.protocol_binding.nil?
|
107
108
|
root.attributes['ForceAuthn'] = settings.force_authn unless settings.force_authn.nil?
|
@@ -3,6 +3,7 @@ require "zlib"
|
|
3
3
|
require "cgi"
|
4
4
|
require 'rexml/document'
|
5
5
|
require "onelogin/ruby-saml/utils"
|
6
|
+
require "onelogin/ruby-saml/setting_error"
|
6
7
|
|
7
8
|
module OneLogin
|
8
9
|
module RubySaml
|
@@ -23,6 +24,7 @@ module OneLogin
|
|
23
24
|
params.each_pair do |key, value|
|
24
25
|
request_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
|
25
26
|
end
|
27
|
+
raise SettingError.new "Invalid settings, idp_slo_target_url is not set!" if settings.idp_slo_target_url.nil? or settings.idp_slo_target_url.empty?
|
26
28
|
@logout_url = settings.idp_slo_target_url + request_params
|
27
29
|
end
|
28
30
|
|
@@ -103,6 +105,7 @@ module OneLogin
|
|
103
105
|
root.attributes['ID'] = uuid
|
104
106
|
root.attributes['IssueInstant'] = time
|
105
107
|
root.attributes['Version'] = "2.0"
|
108
|
+
root.attributes['Destination'] = settings.idp_slo_target_url unless settings.idp_slo_target_url.nil? or settings.idp_slo_target_url.empty?
|
106
109
|
|
107
110
|
if settings.sp_entity_id
|
108
111
|
issuer = root.add_element "saml:Issuer", { "xmlns:saml" => "urn:oasis:names:tc:SAML:2.0:assertion" }
|
@@ -1,7 +1,5 @@
|
|
1
1
|
require "xml_security"
|
2
2
|
require "time"
|
3
|
-
require "base64"
|
4
|
-
require "zlib"
|
5
3
|
|
6
4
|
module OneLogin
|
7
5
|
module RubySaml
|
@@ -30,7 +28,7 @@ module OneLogin
|
|
30
28
|
self.settings = settings
|
31
29
|
|
32
30
|
@options = options
|
33
|
-
@response =
|
31
|
+
@response = OneLogin::RubySaml::Utils.decode_raw_saml(response)
|
34
32
|
@document = XMLSecurity::SignedDocument.new(response)
|
35
33
|
end
|
36
34
|
|
@@ -75,27 +73,6 @@ module OneLogin
|
|
75
73
|
|
76
74
|
private
|
77
75
|
|
78
|
-
def decode(encoded)
|
79
|
-
Base64.decode64(encoded)
|
80
|
-
end
|
81
|
-
|
82
|
-
def inflate(deflated)
|
83
|
-
zlib = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
84
|
-
zlib.inflate(deflated)
|
85
|
-
end
|
86
|
-
|
87
|
-
def decode_raw_response(response)
|
88
|
-
if response =~ /^</
|
89
|
-
return response
|
90
|
-
elsif (decoded = decode(response)) =~ /^</
|
91
|
-
return decoded
|
92
|
-
elsif (inflated = inflate(decoded)) =~ /^</
|
93
|
-
return inflated
|
94
|
-
end
|
95
|
-
|
96
|
-
raise "Couldn't decode SAMLResponse"
|
97
|
-
end
|
98
|
-
|
99
76
|
def valid_saml?(soft = true)
|
100
77
|
Dir.chdir(File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'schemas'))) do
|
101
78
|
@schema = Nokogiri::XML::Schema(IO.read('saml20protocol_schema.xsd'))
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "xml_security"
|
2
2
|
require "time"
|
3
3
|
require "nokogiri"
|
4
|
+
require "onelogin/ruby-saml/utils"
|
4
5
|
require 'onelogin/ruby-saml/attributes'
|
5
6
|
|
6
7
|
# Only supports SAML 2.0
|
@@ -22,7 +23,7 @@ module OneLogin
|
|
22
23
|
def initialize(response, options = {})
|
23
24
|
raise ArgumentError.new("Response cannot be nil") if response.nil?
|
24
25
|
@options = options
|
25
|
-
@response =
|
26
|
+
@response = OneLogin::RubySaml::Utils.decode_raw_saml(response)
|
26
27
|
@document = XMLSecurity::SignedDocument.new(@response)
|
27
28
|
end
|
28
29
|
|
@@ -42,6 +43,8 @@ module OneLogin
|
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
46
|
+
alias nameid name_id
|
47
|
+
|
45
48
|
def sessionindex
|
46
49
|
@sessionindex ||= begin
|
47
50
|
node = xpath_first_from_signed_assertion('/a:AuthnStatement')
|
@@ -147,14 +150,165 @@ module OneLogin
|
|
147
150
|
end
|
148
151
|
|
149
152
|
def validate(soft = true)
|
150
|
-
validate_structure(soft)
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
153
|
+
validate_structure(soft) &&
|
154
|
+
validate_success_status(soft) &&
|
155
|
+
validate_num_assertion &&
|
156
|
+
validate_signed_elements(soft) &&
|
157
|
+
validate_response_state(soft) &&
|
158
|
+
validate_conditions(soft) &&
|
159
|
+
validate_audience(soft) &&
|
160
|
+
validate_signature(soft) &&
|
155
161
|
success?
|
156
162
|
end
|
157
163
|
|
164
|
+
# Validates that the SAML Response only contains a single Assertion (encrypted or not).
|
165
|
+
# @return [Boolean] True if the SAML Response contains one unique Assertion, otherwise False
|
166
|
+
#
|
167
|
+
def validate_num_assertion(soft = true)
|
168
|
+
assertions = REXML::XPath.match(
|
169
|
+
document,
|
170
|
+
"//a:Assertion",
|
171
|
+
{ "a" => ASSERTION }
|
172
|
+
)
|
173
|
+
encrypted_assertions = REXML::XPath.match(
|
174
|
+
document,
|
175
|
+
"//a:EncryptedAssertion",
|
176
|
+
{ "a" => ASSERTION }
|
177
|
+
)
|
178
|
+
|
179
|
+
unless assertions.size + encrypted_assertions.size == 1
|
180
|
+
return soft ? false : validation_error("SAML Response must contain 1 assertion")
|
181
|
+
end
|
182
|
+
|
183
|
+
true
|
184
|
+
end
|
185
|
+
|
186
|
+
# Validates the Signed elements
|
187
|
+
# @return [Boolean] True if there is 1 or 2 Elements signed in the SAML Response
|
188
|
+
# an are a Response or an Assertion Element, otherwise False if soft=True
|
189
|
+
#
|
190
|
+
def validate_signed_elements(soft)
|
191
|
+
signature_nodes = REXML::XPath.match(
|
192
|
+
document,
|
193
|
+
"//ds:Signature",
|
194
|
+
{"ds"=>DSIG}
|
195
|
+
)
|
196
|
+
signed_elements = []
|
197
|
+
verified_seis = []
|
198
|
+
verified_ids = []
|
199
|
+
signature_nodes.each do |signature_node|
|
200
|
+
signed_element = signature_node.parent.name
|
201
|
+
if signed_element != 'Response' && signed_element != 'Assertion'
|
202
|
+
return soft ? false : validation_error("Invalid Signature Element '#{signed_element}'. SAML Response rejected")
|
203
|
+
end
|
204
|
+
|
205
|
+
if signature_node.parent.attributes['ID'].nil?
|
206
|
+
return soft ? false : validation_error("Signed Element must contain an ID. SAML Response rejected")
|
207
|
+
end
|
208
|
+
|
209
|
+
id = signature_node.parent.attributes.get_attribute("ID").value
|
210
|
+
if verified_ids.include?(id)
|
211
|
+
return soft ? false : validation_error("Duplicated ID. SAML Response rejected")
|
212
|
+
end
|
213
|
+
verified_ids.push(id)
|
214
|
+
|
215
|
+
# Check that reference URI matches the parent ID and no duplicate References or IDs
|
216
|
+
ref = REXML::XPath.first(signature_node, ".//ds:Reference", {"ds"=>DSIG})
|
217
|
+
if ref
|
218
|
+
uri = ref.attributes.get_attribute("URI")
|
219
|
+
if uri && !uri.value.empty?
|
220
|
+
sei = uri.value[1..-1]
|
221
|
+
|
222
|
+
unless sei == id
|
223
|
+
return soft ? false : validation_error("Found an invalid Signed Element. SAML Response rejected")
|
224
|
+
end
|
225
|
+
|
226
|
+
if verified_seis.include?(sei)
|
227
|
+
return soft ? false : validation_error("Duplicated Reference URI. SAML Response rejected")
|
228
|
+
end
|
229
|
+
|
230
|
+
verified_seis.push(sei)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
signed_elements << signed_element
|
235
|
+
end
|
236
|
+
|
237
|
+
unless signature_nodes.length < 3 && !signed_elements.empty?
|
238
|
+
return soft ? false : validation_error("Found an unexpected number of Signature Element. SAML Response rejected")
|
239
|
+
end
|
240
|
+
|
241
|
+
true
|
242
|
+
end
|
243
|
+
|
244
|
+
# Validates the Status of the SAML Response
|
245
|
+
# @return [Boolean] True if the SAML Response contains a Success code, otherwise False if soft == false
|
246
|
+
# @raise [ValidationError] if soft == false and validation fails
|
247
|
+
#
|
248
|
+
def validate_success_status(soft = true)
|
249
|
+
return true if success?
|
250
|
+
|
251
|
+
return false unless soft
|
252
|
+
|
253
|
+
error_msg = 'The status code of the Response was not Success'
|
254
|
+
status_error_msg = OneLogin::RubySaml::Utils.status_error_msg(error_msg, status_code, status_message)
|
255
|
+
return validation_error(status_error_msg)
|
256
|
+
end
|
257
|
+
|
258
|
+
# Checks if the Status has the "Success" code
|
259
|
+
# @return [Boolean] True if the StatusCode is Sucess
|
260
|
+
#
|
261
|
+
def success?
|
262
|
+
status_code == "urn:oasis:names:tc:SAML:2.0:status:Success"
|
263
|
+
end
|
264
|
+
|
265
|
+
# @return [String] StatusCode value from a SAML Response.
|
266
|
+
#
|
267
|
+
def status_code
|
268
|
+
@status_code ||= begin
|
269
|
+
nodes = REXML::XPath.match(
|
270
|
+
document,
|
271
|
+
"/p:Response/p:Status/p:StatusCode",
|
272
|
+
{ "p" => PROTOCOL }
|
273
|
+
)
|
274
|
+
if nodes.size == 1
|
275
|
+
node = nodes[0]
|
276
|
+
code = node.attributes["Value"] if node && node.attributes
|
277
|
+
|
278
|
+
unless code == "urn:oasis:names:tc:SAML:2.0:status:Success"
|
279
|
+
nodes = REXML::XPath.match(
|
280
|
+
document,
|
281
|
+
"/p:Response/p:Status/p:StatusCode/p:StatusCode",
|
282
|
+
{ "p" => PROTOCOL }
|
283
|
+
)
|
284
|
+
statuses = nodes.collect do |inner_node|
|
285
|
+
inner_node.attributes["Value"]
|
286
|
+
end
|
287
|
+
extra_code = statuses.join(" | ")
|
288
|
+
if extra_code
|
289
|
+
code = "#{code} | #{extra_code}"
|
290
|
+
end
|
291
|
+
end
|
292
|
+
code
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
# @return [String] the StatusMessage value from a SAML Response.
|
298
|
+
#
|
299
|
+
def status_message
|
300
|
+
@status_message ||= begin
|
301
|
+
nodes = REXML::XPath.match(
|
302
|
+
document,
|
303
|
+
"/p:Response/p:Status/p:StatusMessage",
|
304
|
+
{ "p" => PROTOCOL }
|
305
|
+
)
|
306
|
+
if nodes.size == 1
|
307
|
+
Utils.element_text(nodes.first)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
158
312
|
def validate_structure(soft = true)
|
159
313
|
Dir.chdir(File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'schemas'))) do
|
160
314
|
@schema = Nokogiri::XML::Schema(IO.read('saml20protocol_schema.xsd'))
|
@@ -219,15 +373,6 @@ module OneLogin
|
|
219
373
|
))
|
220
374
|
end
|
221
375
|
|
222
|
-
def get_fingerprint
|
223
|
-
if settings.idp_cert
|
224
|
-
cert = OpenSSL::X509::Certificate.new(settings.idp_cert)
|
225
|
-
Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":")
|
226
|
-
else
|
227
|
-
settings.idp_cert_fingerprint
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
376
|
def validate_conditions(soft = true)
|
232
377
|
return true if conditions.nil?
|
233
378
|
return true if options[:skip_conditions]
|
@@ -245,17 +390,57 @@ module OneLogin
|
|
245
390
|
true
|
246
391
|
end
|
247
392
|
|
393
|
+
def validate_signature(soft = true)
|
394
|
+
error_msg = "Invalid Signature on SAML Response"
|
395
|
+
|
396
|
+
sig_elements = REXML::XPath.match(
|
397
|
+
document,
|
398
|
+
"/p:Response[@ID=$id]/ds:Signature]",
|
399
|
+
{ "p" => PROTOCOL, "ds" => DSIG },
|
400
|
+
{ 'id' => document.signed_element_id }
|
401
|
+
)
|
402
|
+
|
403
|
+
# Check signature nodes
|
404
|
+
if sig_elements.nil? || sig_elements.size == 0
|
405
|
+
sig_elements = REXML::XPath.match(
|
406
|
+
document,
|
407
|
+
"/p:Response/a:Assertion[@ID=$id]/ds:Signature",
|
408
|
+
{"p" => PROTOCOL, "a" => ASSERTION, "ds"=>DSIG},
|
409
|
+
{ 'id' => document.signed_element_id }
|
410
|
+
)
|
411
|
+
end
|
412
|
+
|
413
|
+
if sig_elements.size != 1
|
414
|
+
if sig_elements.size == 0
|
415
|
+
error_msg += ". Signed element id ##{doc.signed_element_id} is not found"
|
416
|
+
else
|
417
|
+
error_msg += ". Signed element id ##{doc.signed_element_id} is found more than once"
|
418
|
+
end
|
419
|
+
return soft ? false : validation_error(error_msg)
|
420
|
+
end
|
421
|
+
|
422
|
+
opts = {}
|
423
|
+
opts[:fingerprint_alg] = OpenSSL::Digest::SHA1.new
|
424
|
+
opts[:cert] = settings.get_idp_cert
|
425
|
+
fingerprint = settings.get_fingerprint
|
426
|
+
|
427
|
+
unless fingerprint
|
428
|
+
return soft ? false : validation_error("No fingerprint or certificate on settings")
|
429
|
+
end
|
430
|
+
|
431
|
+
unless document.validate_document(fingerprint, soft, opts)
|
432
|
+
return soft ? false : validation_error(error_msg)
|
433
|
+
end
|
434
|
+
|
435
|
+
true
|
436
|
+
end
|
437
|
+
|
248
438
|
def parse_time(node, attribute)
|
249
439
|
if node && node.attributes[attribute]
|
250
440
|
Time.parse(node.attributes[attribute])
|
251
441
|
end
|
252
442
|
end
|
253
443
|
|
254
|
-
# Validates the Audience, (If the Audience match the Service Provider EntityID)
|
255
|
-
# If fails, the error is added to the errors array
|
256
|
-
# @return [Boolean] True if there is an Audience Element that match the Service Provider EntityID, otherwise False if soft=True
|
257
|
-
# @raise [ValidationError] if soft == false and validation fails
|
258
|
-
#
|
259
444
|
def validate_audience(soft = true)
|
260
445
|
return true if audiences.empty? || settings.sp_entity_id.nil? || settings.sp_entity_id.empty?
|
261
446
|
|
@@ -267,6 +452,7 @@ module OneLogin
|
|
267
452
|
|
268
453
|
true
|
269
454
|
end
|
455
|
+
|
270
456
|
end
|
271
457
|
end
|
272
458
|
end
|
@@ -117,6 +117,32 @@ module OneLogin
|
|
117
117
|
@single_logout_service_binding = url
|
118
118
|
end
|
119
119
|
|
120
|
+
# Calculates the fingerprint of the IdP x509 certificate.
|
121
|
+
# @return [String] The fingerprint
|
122
|
+
#
|
123
|
+
def get_fingerprint
|
124
|
+
idp_cert_fingerprint || begin
|
125
|
+
idp_cert = get_idp_cert
|
126
|
+
if idp_cert
|
127
|
+
Digest::SHA1.hexdigest(idp_cert.to_der).upcase.scan(/../).join(":")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [OpenSSL::X509::Certificate|nil] Build the IdP certificate from the settings (previously format it)
|
133
|
+
#
|
134
|
+
def get_idp_cert
|
135
|
+
return nil if idp_cert.nil?
|
136
|
+
|
137
|
+
if idp_cert.respond_to?(:to_pem)
|
138
|
+
idp_cert
|
139
|
+
else
|
140
|
+
return nil if idp_cert.empty?
|
141
|
+
formatted_cert = OneLogin::RubySaml::Utils.format_cert(idp_cert)
|
142
|
+
OpenSSL::X509::Certificate.new(formatted_cert)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
120
146
|
# @return [OpenSSL::X509::Certificate|nil] Build the SP certificate from the settings (previously format it)
|
121
147
|
#
|
122
148
|
def get_sp_cert
|