ruby-saml 1.12.4 → 1.13.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.

@@ -21,21 +21,50 @@ module OneLogin
21
21
  #
22
22
  def generate(settings, pretty_print=false, valid_until=nil, cache_duration=nil)
23
23
  meta_doc = XMLSecurity::Document.new
24
+ add_xml_declaration(meta_doc)
25
+ root = add_root_element(meta_doc, settings, valid_until, cache_duration)
26
+ sp_sso = add_sp_sso_element(root, settings)
27
+ add_sp_certificates(sp_sso, settings)
28
+ add_sp_service_elements(sp_sso, settings)
29
+ add_extras(root, settings)
30
+ embed_signature(meta_doc, settings)
31
+ output_xml(meta_doc, pretty_print)
32
+ end
33
+
34
+ protected
35
+
36
+ def add_xml_declaration(meta_doc)
37
+ meta_doc << REXML::XMLDecl.new('1.0', 'UTF-8')
38
+ end
39
+
40
+ def add_root_element(meta_doc, settings, valid_until, cache_duration)
24
41
  namespaces = {
25
42
  "xmlns:md" => "urn:oasis:names:tc:SAML:2.0:metadata"
26
43
  }
44
+
27
45
  if settings.attribute_consuming_service.configured?
28
46
  namespaces["xmlns:saml"] = "urn:oasis:names:tc:SAML:2.0:assertion"
29
47
  end
30
- root = meta_doc.add_element "md:EntityDescriptor", namespaces
31
- sp_sso = root.add_element "md:SPSSODescriptor", {
48
+
49
+ root = meta_doc.add_element("md:EntityDescriptor", namespaces)
50
+ root.attributes["ID"] = OneLogin::RubySaml::Utils.uuid
51
+ root.attributes["entityID"] = settings.sp_entity_id if settings.sp_entity_id
52
+ root.attributes["validUntil"] = valid_until.strftime('%Y-%m-%dT%H:%M:%S%z') if valid_until
53
+ root.attributes["cacheDuration"] = "PT" + cache_duration.to_s + "S" if cache_duration
54
+ root
55
+ end
56
+
57
+ def add_sp_sso_element(root, settings)
58
+ root.add_element "md:SPSSODescriptor", {
32
59
  "protocolSupportEnumeration" => "urn:oasis:names:tc:SAML:2.0:protocol",
33
60
  "AuthnRequestsSigned" => settings.security[:authn_requests_signed],
34
61
  "WantAssertionsSigned" => settings.security[:want_assertions_signed],
35
62
  }
63
+ end
36
64
 
37
- # Add KeyDescriptor if messages will be signed / encrypted
38
- # with SP certificate, and new SP certificate if any
65
+ # Add KeyDescriptor if messages will be signed / encrypted
66
+ # with SP certificate, and new SP certificate if any
67
+ def add_sp_certificates(sp_sso, settings)
39
68
  cert = settings.get_sp_cert
40
69
  cert_new = settings.get_sp_cert_new
41
70
 
@@ -58,16 +87,10 @@ module OneLogin
58
87
  end
59
88
  end
60
89
 
61
- root.attributes["ID"] = OneLogin::RubySaml::Utils.uuid
62
- if settings.sp_entity_id
63
- root.attributes["entityID"] = settings.sp_entity_id
64
- end
65
- if valid_until
66
- root.attributes["validUntil"] = valid_until.strftime('%Y-%m-%dT%H:%M:%S%z')
67
- end
68
- if cache_duration
69
- root.attributes["cacheDuration"] = "PT" + cache_duration.to_s + "S"
70
- end
90
+ sp_sso
91
+ end
92
+
93
+ def add_sp_service_elements(sp_sso, settings)
71
94
  if settings.single_logout_service_url
72
95
  sp_sso.add_element "md:SingleLogoutService", {
73
96
  "Binding" => settings.single_logout_service_binding,
@@ -75,10 +98,12 @@ module OneLogin
75
98
  "ResponseLocation" => settings.single_logout_service_url
76
99
  }
77
100
  end
101
+
78
102
  if settings.name_identifier_format
79
103
  nameid = sp_sso.add_element "md:NameIDFormat"
80
104
  nameid.text = settings.name_identifier_format
81
105
  end
106
+
82
107
  if settings.assertion_consumer_service_url
83
108
  sp_sso.add_element "md:AssertionConsumerService", {
84
109
  "Binding" => settings.assertion_consumer_service_binding,
@@ -117,15 +142,27 @@ module OneLogin
117
142
  # <md:RoleDescriptor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:query="urn:oasis:names:tc:SAML:metadata:ext:query" xsi:type="query:AttributeQueryDescriptorType" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"/>
118
143
  # <md:XACMLAuthzDecisionQueryDescriptor WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"/>
119
144
 
120
- meta_doc << REXML::XMLDecl.new("1.0", "UTF-8")
145
+ sp_sso
146
+ end
121
147
 
122
- # embed signature
123
- if settings.security[:metadata_signed] && settings.private_key && settings.certificate
124
- private_key = settings.get_sp_key
125
- meta_doc.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
126
- end
148
+ # can be overridden in subclass
149
+ def add_extras(root, _settings)
150
+ root
151
+ end
152
+
153
+ def embed_signature(meta_doc, settings)
154
+ return unless settings.security[:metadata_signed]
155
+
156
+ private_key = settings.get_sp_key
157
+ cert = settings.get_sp_cert
158
+ return unless private_key && cert
159
+
160
+ meta_doc.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
161
+ end
162
+
163
+ def output_xml(meta_doc, pretty_print)
164
+ ret = ''
127
165
 
128
- ret = ""
129
166
  # pretty print the XML so IdP administrators can easily see what the SP supports
130
167
  if pretty_print
131
168
  meta_doc.write(ret, 1)
@@ -133,7 +170,7 @@ module OneLogin
133
170
  ret = meta_doc.to_s
134
171
  end
135
172
 
136
- return ret
173
+ ret
137
174
  end
138
175
  end
139
176
  end
@@ -63,7 +63,7 @@ module OneLogin
63
63
  end
64
64
  end
65
65
 
66
- @response = decode_raw_saml(response)
66
+ @response = decode_raw_saml(response, settings)
67
67
  @document = XMLSecurity::SignedDocument.new(@response, @errors)
68
68
 
69
69
  if assertion_encrypted?
@@ -227,11 +227,10 @@ module OneLogin
227
227
  statuses = nodes.collect do |inner_node|
228
228
  inner_node.attributes["Value"]
229
229
  end
230
- extra_code = statuses.join(" | ")
231
- if extra_code
232
- code = "#{code} | #{extra_code}"
233
- end
230
+
231
+ code = [code, statuses].flatten.join(" | ")
234
232
  end
233
+
235
234
  code
236
235
  end
237
236
  end
@@ -338,9 +337,9 @@ module OneLogin
338
337
  end
339
338
 
340
339
  # returns the allowed clock drift on timing validation
341
- # @return [Integer]
340
+ # @return [Float]
342
341
  def allowed_clock_drift
343
- return options[:allowed_clock_drift].to_f
342
+ options[:allowed_clock_drift].to_f.abs + Float::EPSILON
344
343
  end
345
344
 
346
345
  # Checks if the SAML Response contains or not an EncryptedAssertion element
@@ -377,7 +376,6 @@ module OneLogin
377
376
  return false unless validate_response_state
378
377
 
379
378
  validations = [
380
- :validate_response_state,
381
379
  :validate_version,
382
380
  :validate_id,
383
381
  :validate_success_status,
@@ -425,13 +423,12 @@ module OneLogin
425
423
  #
426
424
  def validate_structure
427
425
  structure_error_msg = "Invalid SAML Response. Not match the saml-schema-protocol-2.0.xsd"
428
- check_malformed_doc = check_malformed_doc_enabled?
429
- unless valid_saml?(document, soft, check_malformed_doc)
426
+ unless valid_saml?(document, soft)
430
427
  return append_error(structure_error_msg)
431
428
  end
432
429
 
433
430
  unless decrypted_document.nil?
434
- unless valid_saml?(decrypted_document, soft, check_malformed_doc)
431
+ unless valid_saml?(decrypted_document, soft)
435
432
  return append_error(structure_error_msg)
436
433
  end
437
434
  end
@@ -695,13 +692,13 @@ module OneLogin
695
692
 
696
693
  now = Time.now.utc
697
694
 
698
- if not_before && (now_with_drift = now + allowed_clock_drift) < not_before
699
- error_msg = "Current time is earlier than NotBefore condition (#{now_with_drift} < #{not_before})"
695
+ if not_before && now < (not_before - allowed_clock_drift)
696
+ error_msg = "Current time is earlier than NotBefore condition (#{now} < #{not_before}#{" - #{allowed_clock_drift.ceil}s" if allowed_clock_drift > 0})"
700
697
  return append_error(error_msg)
701
698
  end
702
699
 
703
- if not_on_or_after && now >= (not_on_or_after_with_drift = not_on_or_after + allowed_clock_drift)
704
- error_msg = "Current time is on or after NotOnOrAfter condition (#{now} >= #{not_on_or_after_with_drift})"
700
+ if not_on_or_after && now >= (not_on_or_after + allowed_clock_drift)
701
+ error_msg = "Current time is on or after NotOnOrAfter condition (#{now} >= #{not_on_or_after}#{" + #{allowed_clock_drift.ceil}s" if allowed_clock_drift > 0})"
705
702
  return append_error(error_msg)
706
703
  end
707
704
 
@@ -743,7 +740,7 @@ module OneLogin
743
740
  return true if session_expires_at.nil?
744
741
 
745
742
  now = Time.now.utc
746
- unless (session_expires_at + allowed_clock_drift) > now
743
+ unless now < (session_expires_at + allowed_clock_drift)
747
744
  error_msg = "The attributes have expired, based on the SessionNotOnOrAfter of the AuthnStatement of this Response"
748
745
  return append_error(error_msg)
749
746
  end
@@ -781,8 +778,8 @@ module OneLogin
781
778
 
782
779
  attrs = confirmation_data_node.attributes
783
780
  next if (attrs.include? "InResponseTo" and attrs['InResponseTo'] != in_response_to) ||
784
- (attrs.include? "NotOnOrAfter" and (parse_time(confirmation_data_node, "NotOnOrAfter") + allowed_clock_drift) <= now) ||
785
- (attrs.include? "NotBefore" and parse_time(confirmation_data_node, "NotBefore") > (now + allowed_clock_drift)) ||
781
+ (attrs.include? "NotBefore" and now < (parse_time(confirmation_data_node, "NotBefore") - allowed_clock_drift)) ||
782
+ (attrs.include? "NotOnOrAfter" and now >= (parse_time(confirmation_data_node, "NotOnOrAfter") + allowed_clock_drift)) ||
786
783
  (attrs.include? "Recipient" and !options[:skip_recipient_check] and settings and attrs['Recipient'] != settings.assertion_consumer_service_url)
787
784
 
788
785
  valid_subject_confirmation = true
@@ -866,8 +863,6 @@ module OneLogin
866
863
  fingerprint = settings.get_fingerprint
867
864
  opts[:cert] = idp_cert
868
865
 
869
- check_malformed_doc = check_malformed_doc_enabled?
870
- opts[:check_malformed_doc] = check_malformed_doc
871
866
  if fingerprint && doc.validate_document(fingerprint, @soft, opts)
872
867
  if settings.security[:check_idp_cert_expiration]
873
868
  if OneLogin::RubySaml::Utils.is_cert_expired(idp_cert)
@@ -882,7 +877,7 @@ module OneLogin
882
877
  valid = false
883
878
  expired = false
884
879
  idp_certs[:signing].each do |idp_cert|
885
- valid = doc.validate_document_with_cert(idp_cert, true, check_malformed_doc)
880
+ valid = doc.validate_document_with_cert(idp_cert, true)
886
881
  if valid
887
882
  if settings.security[:check_idp_cert_expiration]
888
883
  if OneLogin::RubySaml::Utils.is_cert_expired(idp_cert)
@@ -1066,10 +1061,6 @@ module OneLogin
1066
1061
  Time.parse(node.attributes[attribute])
1067
1062
  end
1068
1063
  end
1069
-
1070
- def check_malformed_doc_enabled?
1071
- check_malformed_doc?(settings)
1072
- end
1073
1064
  end
1074
1065
  end
1075
1066
  end
@@ -16,14 +16,12 @@ module OneLogin
16
16
  class SamlMessage
17
17
  include REXML
18
18
 
19
- ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
20
- PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
19
+ ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion".freeze
20
+ PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol".freeze
21
21
 
22
22
  BASE64_FORMAT = %r(\A([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?\Z)
23
23
  @@mutex = Mutex.new
24
24
 
25
- MAX_BYTE_SIZE = 250000
26
-
27
25
  # @return [Nokogiri::XML::Schema] Gets the schema object of the SAML 2.0 Protocol schema
28
26
  #
29
27
  def self.schema
@@ -63,13 +61,14 @@ module OneLogin
63
61
  # Validates the SAML Message against the specified schema.
64
62
  # @param document [REXML::Document] The message that will be validated
65
63
  # @param soft [Boolean] soft Enable or Disable the soft mode (In order to raise exceptions when the message is invalid or not)
66
- # @param check_malformed_doc [Boolean] check_malformed_doc Enable or Disable the check for malformed XML
67
64
  # @return [Boolean] True if the XML is valid, otherwise False, if soft=True
68
65
  # @raise [ValidationError] if soft == false and validation fails
69
66
  #
70
- def valid_saml?(document, soft = true, check_malformed_doc = true)
67
+ def valid_saml?(document, soft = true)
71
68
  begin
72
- xml = XMLSecurity::BaseDocument.safe_load_xml(document, check_malformed_doc)
69
+ xml = Nokogiri::XML(document.to_s) do |config|
70
+ config.options = XMLSecurity::BaseDocument::NOKOGIRI_OPTIONS
71
+ end
73
72
  rescue Exception => error
74
73
  return false if soft
75
74
  raise ValidationError.new("XML load failed: #{error.message}")
@@ -87,25 +86,20 @@ module OneLogin
87
86
  # @param saml [String] The deflated and encoded SAML Message
88
87
  # @return [String] The plain SAML Message
89
88
  #
90
- def decode_raw_saml(saml)
89
+ def decode_raw_saml(saml, settings = nil)
91
90
  return saml unless base64_encoded?(saml)
92
91
 
93
- if saml.bytesize > MAX_BYTE_SIZE
94
- raise ValidationError.new("Encoded SAML Message exceeds " + MAX_BYTE_SIZE.to_s + " bytes, so was rejected")
92
+ settings = OneLogin::RubySaml::Settings.new if settings.nil?
93
+ if saml.bytesize > settings.message_max_bytesize
94
+ raise ValidationError.new("Encoded SAML Message exceeds " + settings.message_max_bytesize.to_s + " bytes, so was rejected")
95
95
  end
96
96
 
97
97
  decoded = decode(saml)
98
98
  begin
99
- message = inflate(decoded)
99
+ inflate(decoded)
100
100
  rescue
101
- message = decoded
102
- end
103
-
104
- if message.bytesize > MAX_BYTE_SIZE
105
- raise ValidationError.new("Encoded SAML Message exceeds " + MAX_BYTE_SIZE.to_s + " bytes, so was rejected")
101
+ decoded
106
102
  end
107
-
108
- message
109
103
  end
110
104
 
111
105
  # Deflate, base64 encode and url-encode a SAML Message (To be used in the HTTP-redirect binding)
@@ -162,12 +156,6 @@ module OneLogin
162
156
  def deflate(inflated)
163
157
  Zlib::Deflate.deflate(inflated, 9)[2..-5]
164
158
  end
165
-
166
- def check_malformed_doc?(settings)
167
- default_value = OneLogin::RubySaml::Settings::DEFAULTS[:check_malformed_doc]
168
-
169
- settings.nil? ? default_value : settings.check_malformed_doc
170
- end
171
159
  end
172
160
  end
173
161
  end
@@ -31,9 +31,8 @@ module OneLogin
31
31
 
32
32
  # IdP Data
33
33
  attr_accessor :idp_entity_id
34
-
35
- attr_accessor :idp_sso_service_url
36
- attr_accessor :idp_slo_service_url
34
+ attr_writer :idp_sso_service_url
35
+ attr_writer :idp_slo_service_url
37
36
  attr_accessor :idp_slo_response_service_url
38
37
  attr_accessor :idp_cert
39
38
  attr_accessor :idp_cert_fingerprint
@@ -43,8 +42,10 @@ module OneLogin
43
42
  attr_accessor :idp_name_qualifier
44
43
  attr_accessor :valid_until
45
44
  # SP Data
45
+ attr_writer :sp_entity_id
46
46
  attr_accessor :assertion_consumer_service_url
47
- attr_accessor :assertion_consumer_service_binding
47
+ attr_reader :assertion_consumer_service_binding
48
+ attr_writer :single_logout_service_url
48
49
  attr_accessor :sp_name_qualifier
49
50
  attr_accessor :name_identifier_format
50
51
  attr_accessor :name_identifier_value
@@ -53,9 +54,9 @@ module OneLogin
53
54
  attr_accessor :compress_request
54
55
  attr_accessor :compress_response
55
56
  attr_accessor :double_quote_xml_attribute_values
56
- attr_accessor :check_malformed_doc
57
+ attr_accessor :message_max_bytesize
57
58
  attr_accessor :passive
58
- attr_accessor :protocol_binding
59
+ attr_reader :protocol_binding
59
60
  attr_accessor :attributes_index
60
61
  attr_accessor :force_authn
61
62
  attr_accessor :certificate
@@ -68,9 +69,9 @@ module OneLogin
68
69
  # Work-flow
69
70
  attr_accessor :security
70
71
  attr_accessor :soft
71
- # Compability
72
+ # Deprecated
72
73
  attr_accessor :assertion_consumer_logout_service_url
73
- attr_accessor :assertion_consumer_logout_service_binding
74
+ attr_reader :assertion_consumer_logout_service_binding
74
75
  attr_accessor :issuer
75
76
  attr_accessor :idp_sso_target_url
76
77
  attr_accessor :idp_slo_target_url
@@ -78,94 +79,89 @@ module OneLogin
78
79
  # @return [String] IdP Single Sign On Service URL
79
80
  #
80
81
  def idp_sso_service_url
81
- val = nil
82
- if @idp_sso_service_url.nil?
83
- if @idp_sso_target_url
84
- val = @idp_sso_target_url
85
- end
86
- else
87
- val = @idp_sso_service_url
88
- end
89
- val
82
+ @idp_sso_service_url || @idp_sso_target_url
90
83
  end
91
84
 
92
85
  # @return [String] IdP Single Logout Service URL
93
86
  #
94
87
  def idp_slo_service_url
95
- val = nil
96
- if @idp_slo_service_url.nil?
97
- if @idp_slo_target_url
98
- val = @idp_slo_target_url
99
- end
100
- else
101
- val = @idp_slo_service_url
102
- end
103
- val
88
+ @idp_slo_service_url || @idp_slo_target_url
89
+ end
90
+
91
+ # @return [String] IdP Single Sign On Service Binding
92
+ #
93
+ def idp_sso_service_binding
94
+ @idp_sso_service_binding || idp_binding_from_embed_sign
95
+ end
96
+
97
+ # Setter for IdP Single Sign On Service Binding
98
+ # @param value [String, Symbol].
99
+ #
100
+ def idp_sso_service_binding=(value)
101
+ @idp_sso_service_binding = get_binding(value)
102
+ end
103
+
104
+ # @return [String] IdP Single Logout Service Binding
105
+ #
106
+ def idp_slo_service_binding
107
+ @idp_slo_service_binding || idp_binding_from_embed_sign
108
+ end
109
+
110
+ # Setter for IdP Single Logout Service Binding
111
+ # @param value [String, Symbol].
112
+ #
113
+ def idp_slo_service_binding=(value)
114
+ @idp_slo_service_binding = get_binding(value)
104
115
  end
105
116
 
106
117
  # @return [String] SP Entity ID
107
118
  #
108
119
  def sp_entity_id
109
- val = nil
110
- if @sp_entity_id.nil?
111
- if @issuer
112
- val = @issuer
113
- end
114
- else
115
- val = @sp_entity_id
116
- end
117
- val
120
+ @sp_entity_id || @issuer
118
121
  end
119
122
 
120
- # Setter for SP Entity ID.
121
- # @param val [String].
123
+ # Setter for SP Protocol Binding
124
+ # @param value [String, Symbol].
122
125
  #
123
- def sp_entity_id=(val)
124
- @sp_entity_id = val
126
+ def protocol_binding=(value)
127
+ @protocol_binding = get_binding(value)
125
128
  end
126
129
 
127
- # @return [String] Single Logout Service URL.
130
+ # Setter for SP Assertion Consumer Service Binding
131
+ # @param value [String, Symbol].
128
132
  #
129
- def single_logout_service_url
130
- val = nil
131
- if @single_logout_service_url.nil?
132
- if @assertion_consumer_logout_service_url
133
- val = @assertion_consumer_logout_service_url
134
- end
135
- else
136
- val = @single_logout_service_url
137
- end
138
- val
133
+ def assertion_consumer_service_binding=(value)
134
+ @assertion_consumer_service_binding = get_binding(value)
139
135
  end
140
136
 
141
- # Setter for the Single Logout Service URL.
142
- # @param url [String].
137
+ # @return [String] Single Logout Service URL.
143
138
  #
144
- def single_logout_service_url=(url)
145
- @single_logout_service_url = url
139
+ def single_logout_service_url
140
+ @single_logout_service_url || @assertion_consumer_logout_service_url
146
141
  end
147
142
 
148
143
  # @return [String] Single Logout Service Binding.
149
144
  #
150
145
  def single_logout_service_binding
151
- val = nil
152
- if @single_logout_service_binding.nil?
153
- if @assertion_consumer_logout_service_binding
154
- val = @assertion_consumer_logout_service_binding
155
- end
156
- else
157
- val = @single_logout_service_binding
158
- end
159
- val
146
+ @single_logout_service_binding || @assertion_consumer_logout_service_binding
160
147
  end
161
148
 
162
149
  # Setter for Single Logout Service Binding.
163
150
  #
164
151
  # (Currently we only support "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect")
165
- # @param url [String]
152
+ # @param value [String, Symbol]
166
153
  #
167
- def single_logout_service_binding=(url)
168
- @single_logout_service_binding = url
154
+ def single_logout_service_binding=(value)
155
+ @single_logout_service_binding = get_binding(value)
156
+ end
157
+
158
+ # @deprecated Setter for legacy Single Logout Service Binding parameter.
159
+ #
160
+ # (Currently we only support "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect")
161
+ # @param value [String, Symbol]
162
+ #
163
+ def assertion_consumer_logout_service_binding=(value)
164
+ @assertion_consumer_logout_service_binding = get_binding(value)
169
165
  end
170
166
 
171
167
  # Calculates the fingerprint of the IdP x509 certificate.
@@ -253,14 +249,24 @@ module OneLogin
253
249
 
254
250
  private
255
251
 
252
+ def idp_binding_from_embed_sign
253
+ security[:embed_sign] ? Utils::BINDINGS[:post] : Utils::BINDINGS[:redirect]
254
+ end
255
+
256
+ def get_binding(value)
257
+ return unless value
258
+
259
+ Utils::BINDINGS[value.to_sym] || value
260
+ end
261
+
256
262
  DEFAULTS = {
257
- :assertion_consumer_service_binding => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST".freeze,
258
- :single_logout_service_binding => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect".freeze,
263
+ :assertion_consumer_service_binding => Utils::BINDINGS[:post],
264
+ :single_logout_service_binding => Utils::BINDINGS[:redirect],
259
265
  :idp_cert_fingerprint_algorithm => XMLSecurity::Document::SHA1,
260
266
  :compress_request => true,
261
267
  :compress_response => true,
268
+ :message_max_bytesize => 250000,
262
269
  :soft => true,
263
- :check_malformed_doc => true,
264
270
  :double_quote_xml_attribute_values => false,
265
271
  :security => {
266
272
  :authn_requests_signed => false,
@@ -270,7 +276,7 @@ module OneLogin
270
276
  :want_assertions_encrypted => false,
271
277
  :want_name_id => false,
272
278
  :metadata_signed => false,
273
- :embed_sign => false,
279
+ :embed_sign => false, # Deprecated
274
280
  :digest_method => XMLSecurity::Document::SHA1,
275
281
  :signature_method => XMLSecurity::Document::RSA_SHA1,
276
282
  :check_idp_cert_expiration => false,
@@ -43,7 +43,7 @@ module OneLogin
43
43
  end
44
44
  end
45
45
 
46
- @request = decode_raw_saml(request)
46
+ @request = decode_raw_saml(request, settings)
47
47
  @document = REXML::Document.new(@request)
48
48
  end
49
49
 
@@ -130,6 +130,12 @@ module OneLogin
130
130
 
131
131
  private
132
132
 
133
+ # returns the allowed clock drift on timing validation
134
+ # @return [Float]
135
+ def allowed_clock_drift
136
+ options[:allowed_clock_drift].to_f.abs + Float::EPSILON
137
+ end
138
+
133
139
  # Hard aux function to validate the Logout Request
134
140
  # @param collect_errors [Boolean] Stop validation when first error appears or keep validating. (if soft=true)
135
141
  # @return [Boolean] TRUE if the Logout Request is valid
@@ -180,15 +186,17 @@ module OneLogin
180
186
  true
181
187
  end
182
188
 
183
- # Validates the time. (If the logout request was initialized with the :allowed_clock_drift option, the timing validations are relaxed by the allowed_clock_drift value)
189
+ # Validates the time. (If the logout request was initialized with the :allowed_clock_drift
190
+ # option, the timing validations are relaxed by the allowed_clock_drift value)
184
191
  # If fails, the error is added to the errors array
185
192
  # @return [Boolean] True if satisfies the conditions, otherwise False if soft=True
186
193
  # @raise [ValidationError] if soft == false and validation fails
187
194
  #
188
195
  def validate_not_on_or_after
189
196
  now = Time.now.utc
190
- if not_on_or_after && now >= (not_on_or_after + (options[:allowed_clock_drift] || 0))
191
- return append_error("Current time is on or after NotOnOrAfter (#{now} >= #{not_on_or_after})")
197
+
198
+ if not_on_or_after && now >= (not_on_or_after + allowed_clock_drift)
199
+ return append_error("Current time is on or after NotOnOrAfter (#{now} >= #{not_on_or_after}#{" + #{allowed_clock_drift.ceil}s" if allowed_clock_drift > 0})")
192
200
  end
193
201
 
194
202
  true
@@ -199,8 +207,7 @@ module OneLogin
199
207
  # @raise [ValidationError] if soft == false and validation fails
200
208
  #
201
209
  def validate_structure
202
- check_malformed_doc = check_malformed_doc?(settings)
203
- unless valid_saml?(document, soft, check_malformed_doc)
210
+ unless valid_saml?(document, soft)
204
211
  return append_error("Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd")
205
212
  end
206
213
 
@@ -79,7 +79,7 @@ module OneLogin
79
79
  base64_response = encode(response)
80
80
  response_params = {"SAMLResponse" => base64_response}
81
81
 
82
- if settings.security[:logout_responses_signed] && !settings.security[:embed_sign] && settings.private_key
82
+ if settings.idp_slo_service_binding == Utils::BINDINGS[:redirect] && settings.security[:logout_responses_signed] && settings.private_key
83
83
  params['SigAlg'] = settings.security[:signature_method]
84
84
  url_string = OneLogin::RubySaml::Utils.build_query(
85
85
  :type => 'SAMLResponse',
@@ -150,7 +150,7 @@ module OneLogin
150
150
 
151
151
  def sign_document(document, settings)
152
152
  # embed signature
153
- if settings.security[:logout_responses_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
153
+ if settings.idp_slo_service_binding == Utils::BINDINGS[:post] && settings.private_key && settings.certificate
154
154
  private_key = settings.get_sp_key
155
155
  cert = settings.get_sp_cert
156
156
  document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])