ruby-saml 1.10.2 → 1.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d41dad289f19495a49ad8be046bfc6c37fdcddb5
4
- data.tar.gz: 461bc5c8000ea0124e59cc5782b997c445591e75
3
+ metadata.gz: afcd8a95f66ec94e3bb68b5a5264a651ae623923
4
+ data.tar.gz: eb05bc60959fde11ac20b0af0d14c07b7c5c1b38
5
5
  SHA512:
6
- metadata.gz: 677d7efd58ec482570901bec9ec0c1ef1e234715f2df3ba8983e9202c6af7d50a7dc9b58e4adf2bcb6ac88ba90190866bd16624308f6ce14205f3047587dc38e
7
- data.tar.gz: 084285a2d56ae772430587a3e748e017c1a50cb6090ed1d4990545c0c5e46a8ecf8c20d5de04b284897e81a35f7da33a2e437686fc181a5ea7085af1121244fd
6
+ metadata.gz: e85dc90f8f4bd5433f0078a6b5e316109dc7bbbe1ba60d5f8075d1f5047a71c208144d1da51157cf7220f2c56fb8b421e7b70ac5c828bea713146fc6bc774a29
7
+ data.tar.gz: 7cce3fd10ff5d7753d518b847b7f0ff0976b4ef5a1b7cc39c6e6cd3c8b32df7649e95ab929631b9838df5a4fb3eb3f3c50479f54253094b457a484710381b8f1
@@ -1,19 +1,18 @@
1
- sudo: false
2
1
  language: ruby
3
2
  rvm:
4
3
  - 1.8.7
5
4
  - 1.9.3
6
5
  - 2.0.0
7
- - 2.1.5
8
- - 2.2.0
9
- - 2.3.0
10
- - 2.4.0
11
- - 2.5.0
12
- - 2.6.0
6
+ - 2.1.10
7
+ - 2.2.10
8
+ - 2.3.8
9
+ - 2.4.6
10
+ - 2.5.5
11
+ - 2.6.3
13
12
  - ree
14
13
  - jruby-1.7.27
15
14
  - jruby-9.1.17.0
16
- - jruby-9.2.0.0
15
+ - jruby-9.2.7.0
17
16
  gemfile:
18
17
  - Gemfile
19
18
  - gemfiles/nokogiri-1.5.gemfile
@@ -29,19 +28,19 @@ matrix:
29
28
  gemfile: gemfiles/nokogiri-1.5.gemfile
30
29
  - rvm: jruby-9.1.17.0
31
30
  gemfile: gemfiles/nokogiri-1.5.gemfile
32
- - rvm: jruby-9.2.0.0
31
+ - rvm: jruby-9.2.7.0
33
32
  gemfile: gemfiles/nokogiri-1.5.gemfile
34
33
  - rvm: 2.1.5
35
34
  gemfile: gemfiles/nokogiri-1.5.gemfile
36
- - rvm: 2.2.0
35
+ - rvm: 2.2.10
37
36
  gemfile: gemfiles/nokogiri-1.5.gemfile
38
- - rvm: 2.3.0
37
+ - rvm: 2.3.8
39
38
  gemfile: gemfiles/nokogiri-1.5.gemfile
40
- - rvm: 2.4.0
39
+ - rvm: 2.4.6
41
40
  gemfile: gemfiles/nokogiri-1.5.gemfile
42
- - rvm: 2.5.0
41
+ - rvm: 2.5.5
43
42
  gemfile: gemfiles/nokogiri-1.5.gemfile
44
- - rvm: 2.6.0
43
+ - rvm: 2.6.3
45
44
  gemfile: gemfiles/nokogiri-1.5.gemfile
46
45
  env:
47
46
  - JRUBY_OPTS="--debug"
data/README.md CHANGED
@@ -123,6 +123,17 @@ We created a demo project for Rails4 that uses the latest version of this librar
123
123
 
124
124
  If you believe you have discovered a security vulnerability in this gem, please report it at https://www.onelogin.com/security with a description. We follow responsible disclosure guidelines, and will work with you to quickly find a resolution.
125
125
 
126
+ ### Security warning
127
+
128
+ Some tools may incorrectly report ruby-saml is a potential security vulnerability.
129
+ ruby-saml depends on Nokogiri, and it's possible to use Nokogiri in a dangerous way
130
+ (by enabling its DTDLOAD option and disabling its NONET option).
131
+ This dangerous Nokogiri configuration, which is sometimes used by other components,
132
+ can create an XML External Entity (XXE) vulnerability if the XML data is not trusted.
133
+ However, ruby-saml never enables this dangerous Nokogiri configuration;
134
+ ruby-saml never enables DTDLOAD, and it never disables NONET.
135
+
136
+
126
137
  ## Getting Started
127
138
  In order to use the toolkit you will need to install the gem (either manually or using Bundler), and require the library in your Ruby application:
128
139
 
@@ -238,7 +249,7 @@ def saml_settings
238
249
  settings = OneLogin::RubySaml::Settings.new
239
250
 
240
251
  settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
241
- settings.issuer = "http://#{request.host}/saml/metadata"
252
+ settings.sp_entity_id = "http://#{request.host}/saml/metadata"
242
253
  settings.idp_entity_id = "https://app.onelogin.com/saml/metadata/#{OneLoginAppId}"
243
254
  settings.idp_sso_target_url = "https://app.onelogin.com/trust/saml2/http-post/sso/#{OneLoginAppId}"
244
255
  settings.idp_slo_target_url = "https://app.onelogin.com/trust/saml2/http-redirect/slo/#{OneLoginAppId}"
@@ -262,6 +273,8 @@ def saml_settings
262
273
  end
263
274
  ```
264
275
 
276
+ The use of settings.issuer is deprecated in favour of settings.sp_entity_id
277
+
265
278
  Some assertion validations can be skipped by passing parameters to `OneLogin::RubySaml::Response.new()`. For example, you can skip the `AuthnStatement`, `Conditions`, `Recipient`, or the `SubjectConfirmation` validations by initializing the response with different options:
266
279
 
267
280
  ```ruby
@@ -301,7 +314,7 @@ class SamlController < ApplicationController
301
314
  settings = OneLogin::RubySaml::Settings.new
302
315
 
303
316
  settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
304
- settings.issuer = "http://#{request.host}/saml/metadata"
317
+ settings.sp_entity_id = "http://#{request.host}/saml/metadata"
305
318
  settings.idp_sso_target_url = "https://app.onelogin.com/saml/signon/#{OneLoginAppId}"
306
319
  settings.idp_cert_fingerprint = OneLoginAppCertFingerPrint
307
320
  settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
@@ -364,7 +377,7 @@ def saml_settings
364
377
  settings = idp_metadata_parser.parse_remote("https://example.com/auth/saml2/idp/metadata")
365
378
 
366
379
  settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
367
- settings.issuer = "http://#{request.host}/saml/metadata"
380
+ settings.sp_entity_id = "http://#{request.host}/saml/metadata"
368
381
  settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
369
382
  # Optional for most SAML IdPs
370
383
  settings.authn_context = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
@@ -378,8 +391,8 @@ The following attributes are set:
378
391
  * idp_sso_target_url
379
392
  * idp_slo_target_url
380
393
  * idp_attribute_names
381
- * idp_cert
382
- * idp_cert_fingerprint
394
+ * idp_cert
395
+ * idp_cert_fingerprint
383
396
  * idp_cert_multi
384
397
 
385
398
  ### Retrieve one Entity Descriptor when many exist in Metadata
@@ -548,6 +561,8 @@ The settings related to sign are stored in the `security` attribute of the setti
548
561
  # Embeded signature or HTTP GET parameter signature
549
562
  # Note that metadata signature is always embedded regardless of this value.
550
563
  settings.security[:embed_sign] = false
564
+ settings.security[:check_idp_cert_expiration] = false # Enable or not IdP x509 cert expiration check
565
+ settings.security[:check_sp_cert_expiration] = false # Enable or not SP x509 cert expiration check
551
566
  ```
552
567
 
553
568
  Notice that the RelayState parameter is used when creating the Signature on the HTTP-Redirect Binding.
@@ -117,9 +117,9 @@ module OneLogin
117
117
  if settings.assertion_consumer_service_url != nil
118
118
  root.attributes["AssertionConsumerServiceURL"] = settings.assertion_consumer_service_url
119
119
  end
120
- if settings.issuer != nil
120
+ if settings.sp_entity_id != nil
121
121
  issuer = root.add_element "saml:Issuer"
122
- issuer.text = settings.issuer
122
+ issuer.text = settings.sp_entity_id
123
123
  end
124
124
 
125
125
  if settings.name_identifier_value_requested != nil
@@ -8,9 +8,9 @@ module OneLogin
8
8
 
9
9
  def self.logger
10
10
  @logger ||= begin
11
- (defined?(::Rails) && Rails.respond_to?(:logger) && Rails.logger) ||
12
- DEFAULT_LOGGER
13
- end
11
+ (defined?(::Rails) && Rails.respond_to?(:logger) && Rails.logger) ||
12
+ DEFAULT_LOGGER
13
+ end
14
14
  end
15
15
 
16
16
  def self.logger=(logger)
@@ -105,9 +105,9 @@ module OneLogin
105
105
  root.attributes['Version'] = "2.0"
106
106
  root.attributes['Destination'] = settings.idp_slo_target_url unless settings.idp_slo_target_url.nil?
107
107
 
108
- if settings.issuer
108
+ if settings.sp_entity_id
109
109
  issuer = root.add_element "saml:Issuer"
110
- issuer.text = settings.issuer
110
+ issuer.text = settings.sp_entity_id
111
111
  end
112
112
 
113
113
  nameid = root.add_element "saml:NameID"
@@ -163,7 +163,7 @@ module OneLogin
163
163
 
164
164
  return append_error("No settings on logout response") if settings.nil?
165
165
 
166
- return append_error("No issuer in settings of the logout response") if settings.issuer.nil?
166
+ return append_error("No sp_entity_id in settings of the logout response") if settings.sp_entity_id.nil?
167
167
 
168
168
  if settings.idp_cert_fingerprint.nil? && settings.idp_cert.nil? && settings.idp_cert_multi.nil?
169
169
  return append_error("No fingerprint or certificate on settings of the logout response")
@@ -228,13 +228,19 @@ module OneLogin
228
228
  :raw_sig_alg => options[:raw_get_params]['SigAlg']
229
229
  )
230
230
 
231
+ expired = false
231
232
  if idp_certs.nil? || idp_certs[:signing].empty?
232
233
  valid = OneLogin::RubySaml::Utils.verify_signature(
233
- :cert => settings.get_idp_cert,
234
+ :cert => idp_cert,
234
235
  :sig_alg => options[:get_params]['SigAlg'],
235
236
  :signature => options[:get_params]['Signature'],
236
237
  :query_string => query_string
237
238
  )
239
+ if valid && settings.security[:check_idp_cert_expiration]
240
+ if OneLogin::RubySaml::Utils.is_cert_expired(idp_cert)
241
+ expired = true
242
+ end
243
+ end
238
244
  else
239
245
  valid = false
240
246
  idp_certs[:signing].each do |signing_idp_cert|
@@ -245,11 +251,20 @@ module OneLogin
245
251
  :query_string => query_string
246
252
  )
247
253
  if valid
254
+ if settings.security[:check_idp_cert_expiration]
255
+ if OneLogin::RubySaml::Utils.is_cert_expired(signing_idp_cert)
256
+ expired = true
257
+ end
258
+ end
248
259
  break
249
260
  end
250
261
  end
251
262
  end
252
263
 
264
+ if expired
265
+ error_msg = "IdP x509 certificate expired"
266
+ return append_error(error_msg)
267
+ end
253
268
  unless valid
254
269
  error_msg = "Invalid Signature on Logout Response"
255
270
  return append_error(error_msg)
@@ -57,8 +57,8 @@ module OneLogin
57
57
  end
58
58
 
59
59
  root.attributes["ID"] = OneLogin::RubySaml::Utils.uuid
60
- if settings.issuer
61
- root.attributes["entityID"] = settings.issuer
60
+ if settings.sp_entity_id
61
+ root.attributes["entityID"] = settings.sp_entity_id
62
62
  end
63
63
  if settings.single_logout_service_url
64
64
  sp_sso.add_element "md:SingleLogoutService", {
@@ -589,11 +589,11 @@ module OneLogin
589
589
  # @raise [ValidationError] if soft == false and validation fails
590
590
  #
591
591
  def validate_audience
592
- return true if audiences.empty? || settings.issuer.nil? || settings.issuer.empty?
592
+ return true if audiences.empty? || settings.sp_entity_id.nil? || settings.sp_entity_id.empty?
593
593
 
594
- unless audiences.include? settings.issuer
594
+ unless audiences.include? settings.sp_entity_id
595
595
  s = audiences.count > 1 ? 's' : '';
596
- error_msg = "Invalid Audience#{s}. The audience#{s} #{audiences.join(',')}, did not match the expected audience #{settings.issuer}"
596
+ error_msg = "Invalid Audience#{s}. The audience#{s} #{audiences.join(',')}, did not match the expected audience #{settings.sp_entity_id}"
597
597
  return append_error(error_msg)
598
598
  end
599
599
 
@@ -781,8 +781,8 @@ module OneLogin
781
781
  return append_error("An empty NameID value found")
782
782
  end
783
783
 
784
- unless settings.issuer.nil? || settings.issuer.empty? || name_id_spnamequalifier.nil? || name_id_spnamequalifier.empty?
785
- if name_id_spnamequalifier != settings.issuer
784
+ unless settings.sp_entity_id.nil? || settings.sp_entity_id.empty? || name_id_spnamequalifier.nil? || name_id_spnamequalifier.empty?
785
+ if name_id_spnamequalifier != settings.sp_entity_id
786
786
  return append_error("The SPNameQualifier value mistmatch the SP entityID value.")
787
787
  end
788
788
  end
@@ -829,24 +829,43 @@ module OneLogin
829
829
  return append_error(error_msg)
830
830
  end
831
831
 
832
+
832
833
  idp_certs = settings.get_idp_cert_multi
833
834
  if idp_certs.nil? || idp_certs[:signing].empty?
834
835
  opts = {}
835
836
  opts[:fingerprint_alg] = settings.idp_cert_fingerprint_algorithm
836
- opts[:cert] = settings.get_idp_cert
837
+ idp_cert = settings.get_idp_cert
837
838
  fingerprint = settings.get_fingerprint
839
+ opts[:cert] = idp_cert
838
840
 
839
- unless fingerprint && doc.validate_document(fingerprint, @soft, opts)
841
+ if fingerprint && doc.validate_document(fingerprint, @soft, opts)
842
+ if settings.security[:check_idp_cert_expiration]
843
+ if OneLogin::RubySaml::Utils.is_cert_expired(idp_cert)
844
+ error_msg = "IdP x509 certificate expired"
845
+ return append_error(error_msg)
846
+ end
847
+ end
848
+ else
840
849
  return append_error(error_msg)
841
850
  end
842
851
  else
843
852
  valid = false
853
+ expired = false
844
854
  idp_certs[:signing].each do |idp_cert|
845
855
  valid = doc.validate_document_with_cert(idp_cert)
846
856
  if valid
857
+ if settings.security[:check_idp_cert_expiration]
858
+ if OneLogin::RubySaml::Utils.is_cert_expired(idp_cert)
859
+ expired = true
860
+ end
861
+ end
847
862
  break
848
863
  end
849
864
  end
865
+ if expired
866
+ error_msg = "IdP x509 certificate expired"
867
+ return append_error(error_msg)
868
+ end
850
869
  unless valid
851
870
  return append_error(error_msg)
852
871
  end
@@ -1,6 +1,7 @@
1
1
  require "xml_security"
2
2
  require "onelogin/ruby-saml/attribute_service"
3
3
  require "onelogin/ruby-saml/utils"
4
+ require "onelogin/ruby-saml/validation_error"
4
5
 
5
6
  # Only supports SAML 2.0
6
7
  module OneLogin
@@ -40,7 +41,6 @@ module OneLogin
40
41
  attr_accessor :idp_name_qualifier
41
42
  attr_accessor :valid_until
42
43
  # SP Data
43
- attr_accessor :issuer
44
44
  attr_accessor :assertion_consumer_service_url
45
45
  attr_accessor :assertion_consumer_service_binding
46
46
  attr_accessor :sp_name_qualifier
@@ -68,6 +68,28 @@ module OneLogin
68
68
  # Compability
69
69
  attr_accessor :assertion_consumer_logout_service_url
70
70
  attr_accessor :assertion_consumer_logout_service_binding
71
+ attr_accessor :issuer
72
+
73
+ # @return [String] SP Entity ID
74
+ #
75
+ def sp_entity_id
76
+ val = nil
77
+ if @sp_entity_id.nil?
78
+ if @issuer
79
+ val = @issuer
80
+ end
81
+ else
82
+ val = @sp_entity_id
83
+ end
84
+ val
85
+ end
86
+
87
+ # Setter for SP Entity ID.
88
+ # @param val [String].
89
+ #
90
+ def sp_entity_id=(val)
91
+ @sp_entity_id = val
92
+ end
71
93
 
72
94
  # @return [String] Single Logout Service URL.
73
95
  #
@@ -167,7 +189,15 @@ module OneLogin
167
189
  return nil if certificate.nil? || certificate.empty?
168
190
 
169
191
  formatted_cert = OneLogin::RubySaml::Utils.format_cert(certificate)
170
- OpenSSL::X509::Certificate.new(formatted_cert)
192
+ cert = OpenSSL::X509::Certificate.new(formatted_cert)
193
+
194
+ if security[:check_sp_cert_expiration]
195
+ if OneLogin::RubySaml::Utils.is_cert_expired(cert)
196
+ raise OneLogin::RubySaml::ValidationError.new("The SP certificate expired.")
197
+ end
198
+ end
199
+
200
+ cert
171
201
  end
172
202
 
173
203
  # @return [OpenSSL::X509::Certificate|nil] Build the New SP certificate from the settings (previously format it)
@@ -197,6 +227,7 @@ module OneLogin
197
227
  :compress_request => true,
198
228
  :compress_response => true,
199
229
  :soft => true,
230
+ :double_quote_xml_attribute_values => false,
200
231
  :security => {
201
232
  :authn_requests_signed => false,
202
233
  :logout_requests_signed => false,
@@ -207,9 +238,10 @@ module OneLogin
207
238
  :metadata_signed => false,
208
239
  :embed_sign => false,
209
240
  :digest_method => XMLSecurity::Document::SHA1,
210
- :signature_method => XMLSecurity::Document::RSA_SHA1
211
- }.freeze,
212
- :double_quote_xml_attribute_values => false,
241
+ :signature_method => XMLSecurity::Document::RSA_SHA1,
242
+ :check_idp_cert_expiration => false,
243
+ :check_sp_cert_expiration => false
244
+ }.freeze
213
245
  }.freeze
214
246
  end
215
247
  end
@@ -280,13 +280,19 @@ module OneLogin
280
280
  :raw_sig_alg => options[:raw_get_params]['SigAlg']
281
281
  )
282
282
 
283
+ expired = false
283
284
  if idp_certs.nil? || idp_certs[:signing].empty?
284
285
  valid = OneLogin::RubySaml::Utils.verify_signature(
285
- :cert => settings.get_idp_cert,
286
+ :cert => idp_cert,
286
287
  :sig_alg => options[:get_params]['SigAlg'],
287
288
  :signature => options[:get_params]['Signature'],
288
289
  :query_string => query_string
289
290
  )
291
+ if valid && settings.security[:check_idp_cert_expiration]
292
+ if OneLogin::RubySaml::Utils.is_cert_expired(idp_cert)
293
+ expired = true
294
+ end
295
+ end
290
296
  else
291
297
  valid = false
292
298
  idp_certs[:signing].each do |signing_idp_cert|
@@ -297,11 +303,20 @@ module OneLogin
297
303
  :query_string => query_string
298
304
  )
299
305
  if valid
306
+ if settings.security[:check_idp_cert_expiration]
307
+ if OneLogin::RubySaml::Utils.is_cert_expired(signing_idp_cert)
308
+ expired = true
309
+ end
310
+ end
300
311
  break
301
312
  end
302
313
  end
303
314
  end
304
315
 
316
+ if expired
317
+ error_msg = "IdP x509 certificate expired"
318
+ return append_error(error_msg)
319
+ end
305
320
  unless valid
306
321
  return append_error("Invalid Signature on Logout Request")
307
322
  end
@@ -114,9 +114,9 @@ module OneLogin
114
114
  root.attributes['InResponseTo'] = request_id unless request_id.nil?
115
115
  root.attributes['Destination'] = settings.idp_slo_target_url unless settings.idp_slo_target_url.nil?
116
116
 
117
- if settings.issuer != nil
117
+ if settings.sp_entity_id != nil
118
118
  issuer = root.add_element "saml:Issuer"
119
- issuer.text = settings.issuer
119
+ issuer.text = settings.sp_entity_id
120
120
  end
121
121
 
122
122
  # add success message
@@ -3,6 +3,7 @@ if RUBY_VERSION < '1.9'
3
3
  else
4
4
  require 'securerandom'
5
5
  end
6
+ require "openssl"
6
7
 
7
8
  module OneLogin
8
9
  module RubySaml
@@ -15,6 +16,18 @@ module OneLogin
15
16
  DSIG = "http://www.w3.org/2000/09/xmldsig#"
16
17
  XENC = "http://www.w3.org/2001/04/xmlenc#"
17
18
 
19
+ # Checks if the x509 cert provided is expired
20
+ #
21
+ # @param cert [Certificate] The x509 certificate
22
+ #
23
+ def self.is_cert_expired(cert)
24
+ if cert.is_a?(String)
25
+ cert = OpenSSL::X509::Certificate.new(cert)
26
+ end
27
+
28
+ return cert.not_after < Time.now
29
+ end
30
+
18
31
  # Return a properly formatted x509 certificate
19
32
  #
20
33
  # @param cert [String] The original certificate
@@ -1,5 +1,5 @@
1
1
  module OneLogin
2
2
  module RubySaml
3
- VERSION = '1.10.2'
3
+ VERSION = '1.11.0'
4
4
  end
5
5
  end
@@ -17,7 +17,6 @@ Gem::Specification.new do |s|
17
17
  ]
18
18
  s.files = `git ls-files`.split("\n")
19
19
  s.homepage = %q{http://github.com/onelogin/ruby-saml}
20
- s.rubyforge_project = %q{http://www.rubygems.org/gems/ruby-saml}
21
20
  s.rdoc_options = ["--charset=UTF-8"]
22
21
  s.require_paths = ["lib"]
23
22
  s.rubygems_version = %q{1.3.7}
@@ -44,6 +43,7 @@ Gem::Specification.new do |s|
44
43
  s.add_runtime_dependency('nokogiri', '>= 1.5.10')
45
44
  end
46
45
 
46
+ s.add_development_dependency('coveralls')
47
47
  s.add_development_dependency('minitest', '~> 5.5')
48
48
  s.add_development_dependency('mocha', '~> 0.14')
49
49
  s.add_development_dependency('rake', '~> 10')
@@ -62,7 +62,7 @@ class RubySamlTest < Minitest::Test
62
62
 
63
63
  assert logoutresponse.validate
64
64
 
65
- assert_equal settings.issuer, logoutresponse.issuer
65
+ assert_equal settings.sp_entity_id, logoutresponse.issuer
66
66
  assert_equal in_relation_to_request_id, logoutresponse.in_response_to
67
67
 
68
68
  assert logoutresponse.success?
@@ -123,12 +123,13 @@ class RubySamlTest < Minitest::Test
123
123
  assert_includes logoutresponse.errors, "The status code of the Logout Response was not Success, was Requester -> Logoutrequest expired"
124
124
  end
125
125
 
126
- it "invalidate logout response when in lack of issuer setting" do
126
+ it "invalidate logout response when in lack of sp_entity_id setting" do
127
127
  bad_settings = settings
128
128
  bad_settings.issuer = nil
129
+ bad_settings.sp_entity_id = nil
129
130
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_logout_response_document, bad_settings)
130
131
  assert !logoutresponse.validate
131
- assert_includes logoutresponse.errors, "No issuer in settings of the logout response"
132
+ assert_includes logoutresponse.errors, "No sp_entity_id in settings of the logout response"
132
133
  end
133
134
 
134
135
  it "invalidate logout response with wrong issuer" do
@@ -139,7 +140,7 @@ class RubySamlTest < Minitest::Test
139
140
  assert_includes logoutresponse.errors, "Doesn't match the issuer, expected: <#{logoutresponse.settings.idp_entity_id}>, but was: <http://app.muda.no>"
140
141
  end
141
142
 
142
- it "collect errors when collect_errors=true" do
143
+ it "collect errors when collect_errors=true" do
143
144
  settings.idp_entity_id = 'http://invalid.issuer.example.com/'
144
145
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_logout_response_document, settings)
145
146
  collect_errors = true
@@ -184,7 +185,7 @@ class RubySamlTest < Minitest::Test
184
185
  opts = { :matches_request_id => expected_request_id}
185
186
 
186
187
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document, settings, opts)
187
- assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate }
188
+ assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate }
188
189
  assert_includes logoutresponse.errors, "The InResponseTo of the Logout Response: #{logoutresponse.in_response_to}, does not match the ID of the Logout Request sent by the SP: #{expected_request_id}"
189
190
  end
190
191
 
@@ -202,11 +203,12 @@ class RubySamlTest < Minitest::Test
202
203
  assert_includes logoutresponse.errors, "The status code of the Logout Response was not Success, was Requester"
203
204
  end
204
205
 
205
- it "raise validation error when in lack of issuer setting" do
206
+ it "raise validation error when in lack of sp_entity_id setting" do
206
207
  settings.issuer = nil
208
+ settings.sp_entity_id = nil
207
209
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_logout_response_document, settings)
208
210
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate }
209
- assert_includes logoutresponse.errors, "No issuer in settings of the logout response"
211
+ assert_includes logoutresponse.errors, "No sp_entity_id in settings of the logout response"
210
212
  end
211
213
 
212
214
  it "raise validation error when logout response with wrong issuer" do
@@ -392,6 +394,21 @@ class RubySamlTest < Minitest::Test
392
394
  assert logoutresponse_sign_test.send(:validate_signature)
393
395
  end
394
396
 
397
+ it "return false when cert expired and check_idp_cert_expiration expired" do
398
+ params['RelayState'] = params[:RelayState]
399
+ options = {}
400
+ options[:get_params] = params
401
+ settings.security[:check_idp_cert_expiration] = true
402
+ settings.idp_cert = nil
403
+ settings.idp_cert_multi = {
404
+ :signing => [ruby_saml_cert_text],
405
+ :encryption => []
406
+ }
407
+ logoutresponse_sign_test = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
408
+ assert !logoutresponse_sign_test.send(:validate_signature)
409
+ assert_includes logoutresponse_sign_test.errors, "IdP x509 certificate expired"
410
+ end
411
+
395
412
  it "return false when none cert on idp_cert_multi is valid" do
396
413
  params['RelayState'] = params[:RelayState]
397
414
  options = {}
@@ -402,6 +419,7 @@ class RubySamlTest < Minitest::Test
402
419
  }
403
420
  logoutresponse_sign_test = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
404
421
  assert !logoutresponse_sign_test.send(:validate_signature)
422
+ assert_includes logoutresponse_sign_test.errors, "Invalid Signature on Logout Response"
405
423
  end
406
424
  end
407
425
  end
@@ -12,7 +12,7 @@ class MetadataTest < Minitest::Test
12
12
  let(:acs) { REXML::XPath.first(xml_doc, "//md:AssertionConsumerService") }
13
13
 
14
14
  before do
15
- settings.issuer = "https://example.com"
15
+ settings.sp_entity_id = "https://example.com"
16
16
  settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
17
17
  settings.assertion_consumer_service_url = "https://foo.example/saml/consume"
18
18
  end
@@ -259,10 +259,10 @@ class RubySamlTest < Minitest::Test
259
259
 
260
260
  it "raise when there is no valid audience" do
261
261
  settings.idp_cert_fingerprint = signature_fingerprint_1
262
- settings.issuer = 'invalid'
262
+ settings.sp_entity_id = 'invalid'
263
263
  response_valid_signed.settings = settings
264
264
  response_valid_signed.soft = false
265
- error_msg = generate_audience_error(response_valid_signed.settings.issuer, ['https://someone.example.com/audience'])
265
+ error_msg = generate_audience_error(response_valid_signed.settings.sp_entity_id, ['https://someone.example.com/audience'])
266
266
  assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
267
267
  response_valid_signed.is_valid?
268
268
  end
@@ -415,11 +415,11 @@ class RubySamlTest < Minitest::Test
415
415
 
416
416
  it "return false when there is no valid audience" do
417
417
  settings.idp_cert_fingerprint = signature_fingerprint_1
418
- settings.issuer = 'invalid'
418
+ settings.sp_entity_id = 'invalid'
419
419
  response_valid_signed.settings = settings
420
420
  response_valid_signed.is_valid?
421
421
 
422
- assert_includes response_valid_signed.errors, generate_audience_error(response_valid_signed.settings.issuer, ['https://someone.example.com/audience'])
422
+ assert_includes response_valid_signed.errors, generate_audience_error(response_valid_signed.settings.sp_entity_id, ['https://someone.example.com/audience'])
423
423
  end
424
424
 
425
425
  it "return false when no ID present in the SAML Response" do
@@ -451,7 +451,7 @@ class RubySamlTest < Minitest::Test
451
451
 
452
452
  it "collect errors when collect_errors=true" do
453
453
  settings.idp_cert = ruby_saml_cert_text
454
- settings.issuer = 'invalid'
454
+ settings.sp_entity_id = 'invalid'
455
455
  response_invalid_subjectconfirmation_recipient.settings = settings
456
456
  collect_errors = true
457
457
  response_invalid_subjectconfirmation_recipient.is_valid?(collect_errors)
@@ -464,23 +464,23 @@ class RubySamlTest < Minitest::Test
464
464
  describe "#validate_audience" do
465
465
  it "return true when the audience is valid" do
466
466
  response.settings = settings
467
- response.settings.issuer = '{audience}'
467
+ response.settings.sp_entity_id = '{audience}'
468
468
  assert response.send(:validate_audience)
469
469
  assert_empty response.errors
470
470
  end
471
471
 
472
472
  it "return true when the audience is self closing" do
473
473
  response_audience_self_closed.settings = settings
474
- response_audience_self_closed.settings.issuer = '{audience}'
474
+ response_audience_self_closed.settings.sp_entity_id = '{audience}'
475
475
  assert response_audience_self_closed.send(:validate_audience)
476
476
  assert_empty response_audience_self_closed.errors
477
477
  end
478
478
 
479
479
  it "return false when the audience is valid" do
480
480
  response.settings = settings
481
- response.settings.issuer = 'invalid_audience'
481
+ response.settings.sp_entity_id = 'invalid_audience'
482
482
  assert !response.send(:validate_audience)
483
- assert_includes response.errors, generate_audience_error(response.settings.issuer, ['{audience}'])
483
+ assert_includes response.errors, generate_audience_error(response.settings.sp_entity_id, ['{audience}'])
484
484
  end
485
485
  end
486
486
 
@@ -665,23 +665,23 @@ class RubySamlTest < Minitest::Test
665
665
  describe "#validate_audience" do
666
666
  it "return true when the audience is valid" do
667
667
  response_valid_signed.settings = settings
668
- response_valid_signed.settings.issuer = "https://someone.example.com/audience"
668
+ response_valid_signed.settings.sp_entity_id = "https://someone.example.com/audience"
669
669
  assert response_valid_signed.send(:validate_audience)
670
670
  assert_empty response_valid_signed.errors
671
671
  end
672
672
 
673
- it "return true when there is not issuer defined" do
673
+ it "return true when there is not sp_entity_id defined" do
674
674
  response_valid_signed.settings = settings
675
- response_valid_signed.settings.issuer = nil
675
+ response_valid_signed.settings.sp_entity_id = nil
676
676
  assert response_valid_signed.send(:validate_audience)
677
677
  assert_empty response_valid_signed.errors
678
678
  end
679
679
 
680
680
  it "return false when there is no valid audience" do
681
681
  response_invalid_audience.settings = settings
682
- response_invalid_audience.settings.issuer = "https://invalid.example.com/audience"
682
+ response_invalid_audience.settings.sp_entity_id = "https://invalid.example.com/audience"
683
683
  assert !response_invalid_audience.send(:validate_audience)
684
- assert_includes response_invalid_audience.errors, generate_audience_error(response_invalid_audience.settings.issuer, ['http://invalid.audience.com'])
684
+ assert_includes response_invalid_audience.errors, generate_audience_error(response_invalid_audience.settings.sp_entity_id, ['http://invalid.audience.com'])
685
685
  end
686
686
  end
687
687
 
@@ -880,6 +880,15 @@ class RubySamlTest < Minitest::Test
880
880
  assert_includes response_valid_signed_without_x509certificate.errors, "Invalid Signature on SAML Response"
881
881
  end
882
882
 
883
+ it "return false when cert expired and check_idp_cert_expiration enabled" do
884
+ settings.idp_cert_fingerprint = nil
885
+ settings.idp_cert = ruby_saml_cert_text
886
+ settings.security[:check_idp_cert_expiration] = true
887
+ response_valid_signed.settings = settings
888
+ assert !response_valid_signed.send(:validate_signature)
889
+ assert_includes response_valid_signed.errors, "IdP x509 certificate expired"
890
+ end
891
+
883
892
  it "return false when no X509Certificate and the cert provided at settings mismatches" do
884
893
  settings.idp_cert_fingerprint = nil
885
894
  settings.idp_cert = signature_1
@@ -953,7 +962,7 @@ class RubySamlTest < Minitest::Test
953
962
  end
954
963
 
955
964
  it "return false when wrong_spnamequalifier" do
956
- settings.issuer = 'sp_entity_id'
965
+ settings.sp_entity_id = 'sp_entity_id'
957
966
  response_wrong_spnamequalifier.settings = settings
958
967
  assert !response_wrong_spnamequalifier.send(:validate_name_id)
959
968
  assert_includes response_wrong_spnamequalifier.errors, "The SPNameQualifier value mistmatch the SP entityID value."
@@ -966,7 +975,7 @@ class RubySamlTest < Minitest::Test
966
975
  end
967
976
 
968
977
  it "return true when nameid is valid and response_wrong_spnamequalifier matches the SP issuer" do
969
- settings.issuer = 'wrong-sp-entityid'
978
+ settings.sp_entity_id = 'wrong-sp-entityid'
970
979
  response_wrong_spnamequalifier.settings = settings
971
980
  assert response_wrong_spnamequalifier.send(:validate_name_id)
972
981
  end
@@ -1398,7 +1407,7 @@ class RubySamlTest < Minitest::Test
1398
1407
 
1399
1408
  before do
1400
1409
  settings.idp_cert_fingerprint = 'EE:17:4E:FB:A8:81:71:12:0D:2A:78:43:BC:E7:0C:07:58:79:F4:F4'
1401
- settings.issuer = 'http://rubysaml.com:3000/saml/metadata'
1410
+ settings.sp_entity_id = 'http://rubysaml.com:3000/saml/metadata'
1402
1411
  settings.assertion_consumer_service_url = 'http://rubysaml.com:3000/saml/acs'
1403
1412
  settings.certificate = ruby_saml_cert_text
1404
1413
  settings.private_key = ruby_saml_key_text
@@ -1,6 +1,7 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
2
 
3
3
  require 'onelogin/ruby-saml/settings'
4
+ require 'onelogin/ruby-saml/validation_error'
4
5
 
5
6
  class SettingsTest < Minitest::Test
6
7
 
@@ -243,6 +244,13 @@ class SettingsTest < Minitest::Test
243
244
  }
244
245
  end
245
246
 
247
+ it "raises an error if SP certificate expired and check_sp_cert_expiration enabled" do
248
+ @settings.certificate = ruby_saml_cert_text
249
+ @settings.security[:check_sp_cert_expiration] = true
250
+ assert_raises(OneLogin::RubySaml::ValidationError) {
251
+ settings.get_sp_cert
252
+ }
253
+ end
246
254
  end
247
255
 
248
256
  describe "#get_sp_cert_new" do
@@ -429,6 +429,23 @@ class RubySamlTest < Minitest::Test
429
429
  assert logout_request_sign_test.send(:validate_signature)
430
430
  end
431
431
 
432
+ it "return false when cert expired and check_idp_cert_expiration expired" do
433
+ params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
434
+ params['RelayState'] = params[:RelayState]
435
+ options = {}
436
+ options[:get_params] = params
437
+ settings.security[:check_idp_cert_expiration] = true
438
+ logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
439
+ settings.idp_cert = nil
440
+ settings.idp_cert_multi = {
441
+ :signing => [ruby_saml_cert_text],
442
+ :encryption => []
443
+ }
444
+ logout_request_sign_test.settings = settings
445
+ assert !logout_request_sign_test.send(:validate_signature)
446
+ assert_includes logout_request_sign_test.errors, "IdP x509 certificate expired"
447
+ end
448
+
432
449
  it "return false when none cert on idp_cert_multi is valid" do
433
450
  params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
434
451
  params['RelayState'] = params[:RelayState]
@@ -442,6 +459,8 @@ class RubySamlTest < Minitest::Test
442
459
  }
443
460
  logout_request_sign_test.settings = settings
444
461
  assert !logout_request_sign_test.send(:validate_signature)
462
+ assert_includes logout_request_sign_test.errors, "Invalid Signature on Logout Request"
463
+
445
464
  end
446
465
  end
447
466
  end
@@ -1,5 +1,7 @@
1
1
  require 'simplecov'
2
+ require 'coveralls'
2
3
 
4
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
3
5
  SimpleCov.start do
4
6
  add_filter "test/"
5
7
  add_filter "vendor/"
@@ -239,7 +239,7 @@ class XmlSecurityTest < Minitest::Test
239
239
  settings.idp_sso_target_url = "https://idp.example.com/sso"
240
240
  settings.protocol_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
241
241
  settings.idp_slo_target_url = "https://idp.example.com/slo",
242
- settings.issuer = "https://sp.example.com/saml2"
242
+ settings.sp_entity_id = "https://sp.example.com/saml2"
243
243
  settings.assertion_consumer_service_url = "https://sp.example.com/acs"
244
244
  settings.single_logout_service_url = "https://sp.example.com/sls"
245
245
  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.10.2
4
+ version: 1.11.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: 2019-04-29 00:00:00.000000000 Z
11
+ date: 2019-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.5.10
27
+ - !ruby/object:Gem::Dependency
28
+ name: coveralls
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: minitest
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -344,8 +358,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
344
358
  - !ruby/object:Gem::Version
345
359
  version: '0'
346
360
  requirements: []
347
- rubyforge_project: http://www.rubygems.org/gems/ruby-saml
348
- rubygems_version: 2.4.8
361
+ rubyforge_project:
362
+ rubygems_version: 2.5.2.1
349
363
  signing_key:
350
364
  specification_version: 4
351
365
  summary: SAML Ruby Tookit