ruby-saml 0.8.18 → 0.9

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.

Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -6
  4. data/Gemfile +2 -12
  5. data/README.md +363 -35
  6. data/Rakefile +14 -0
  7. data/changelog.md +22 -9
  8. data/lib/onelogin/ruby-saml/attribute_service.rb +34 -0
  9. data/lib/onelogin/ruby-saml/attributes.rb +26 -64
  10. data/lib/onelogin/ruby-saml/authrequest.rb +47 -93
  11. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +87 -0
  12. data/lib/onelogin/ruby-saml/logoutrequest.rb +36 -100
  13. data/lib/onelogin/ruby-saml/logoutresponse.rb +25 -35
  14. data/lib/onelogin/ruby-saml/metadata.rb +46 -16
  15. data/lib/onelogin/ruby-saml/response.rb +63 -373
  16. data/lib/onelogin/ruby-saml/saml_message.rb +78 -0
  17. data/lib/onelogin/ruby-saml/settings.rb +54 -122
  18. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +25 -71
  19. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +37 -102
  20. data/lib/onelogin/ruby-saml/utils.rb +32 -199
  21. data/lib/onelogin/ruby-saml/version.rb +1 -1
  22. data/lib/ruby-saml.rb +5 -2
  23. data/lib/schemas/{saml20assertion_schema.xsd → saml-schema-assertion-2.0.xsd} +283 -283
  24. data/lib/schemas/saml-schema-authn-context-2.0.xsd +23 -0
  25. data/lib/schemas/saml-schema-authn-context-types-2.0.xsd +821 -0
  26. data/lib/schemas/saml-schema-metadata-2.0.xsd +339 -0
  27. data/lib/schemas/{saml20protocol_schema.xsd → saml-schema-protocol-2.0.xsd} +302 -302
  28. data/lib/schemas/sstc-metadata-attr.xsd +35 -0
  29. data/lib/schemas/sstc-saml-attribute-ext.xsd +25 -0
  30. data/lib/schemas/sstc-saml-metadata-algsupport-v1.0.xsd +41 -0
  31. data/lib/schemas/sstc-saml-metadata-ui-v1.0.xsd +89 -0
  32. data/lib/schemas/{xenc_schema.xsd → xenc-schema.xsd} +1 -11
  33. data/lib/schemas/xml.xsd +287 -0
  34. data/lib/schemas/{xmldsig_schema.xsd → xmldsig-core-schema.xsd} +0 -9
  35. data/lib/xml_security.rb +83 -235
  36. data/ruby-saml.gemspec +1 -0
  37. data/test/idp_metadata_parser_test.rb +54 -0
  38. data/test/logoutrequest_test.rb +68 -155
  39. data/test/logoutresponse_test.rb +43 -32
  40. data/test/metadata_test.rb +87 -0
  41. data/test/request_test.rb +102 -99
  42. data/test/response_test.rb +181 -495
  43. data/test/responses/idp_descriptor.xml +3 -0
  44. data/test/responses/logoutresponse_fixtures.rb +7 -8
  45. data/test/responses/response_no_cert_and_encrypted_attrs.xml +29 -0
  46. data/test/responses/response_with_multiple_attribute_values.xml +1 -1
  47. data/test/responses/slo_request.xml +4 -0
  48. data/test/settings_test.rb +25 -112
  49. data/test/slo_logoutrequest_test.rb +40 -50
  50. data/test/slo_logoutresponse_test.rb +86 -185
  51. data/test/test_helper.rb +27 -102
  52. data/test/xml_security_test.rb +114 -337
  53. metadata +30 -81
  54. data/lib/onelogin/ruby-saml/setting_error.rb +0 -6
  55. data/test/certificates/certificate.der +0 -0
  56. data/test/certificates/formatted_certificate +0 -14
  57. data/test/certificates/formatted_chained_certificate +0 -42
  58. data/test/certificates/formatted_private_key +0 -12
  59. data/test/certificates/formatted_rsa_private_key +0 -12
  60. data/test/certificates/invalid_certificate1 +0 -1
  61. data/test/certificates/invalid_certificate2 +0 -1
  62. data/test/certificates/invalid_certificate3 +0 -12
  63. data/test/certificates/invalid_chained_certificate1 +0 -1
  64. data/test/certificates/invalid_private_key1 +0 -1
  65. data/test/certificates/invalid_private_key2 +0 -1
  66. data/test/certificates/invalid_private_key3 +0 -10
  67. data/test/certificates/invalid_rsa_private_key1 +0 -1
  68. data/test/certificates/invalid_rsa_private_key2 +0 -1
  69. data/test/certificates/invalid_rsa_private_key3 +0 -10
  70. data/test/certificates/ruby-saml-2.crt +0 -15
  71. data/test/requests/logoutrequest_fixtures.rb +0 -47
  72. data/test/responses/encrypted_new_attack.xml.base64 +0 -1
  73. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  74. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  75. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  76. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  77. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  78. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  79. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  80. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  81. data/test/responses/response_with_concealed_signed_assertion.xml +0 -51
  82. data/test/responses/response_with_doubled_signed_assertion.xml +0 -49
  83. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  84. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  85. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  86. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  87. data/test/responses/response_wrapped.xml.base64 +0 -150
  88. data/test/responses/valid_response.xml.base64 +0 -1
  89. data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
  90. data/test/utils_test.rb +0 -231
@@ -1,82 +1,48 @@
1
- require "xml_security"
2
- require "onelogin/ruby-saml/utils"
3
-
4
1
  module OneLogin
5
2
  module RubySaml
6
3
  class Settings
7
- def initialize(overrides = {}, keep_security_attributes = false)
8
- if keep_security_attributes
9
- security_attributes = overrides.delete(:security) || {}
10
- config = DEFAULTS.merge(overrides)
11
- config[:security] = DEFAULTS[:security].merge(security_attributes)
12
- else
13
- config = DEFAULTS.merge(overrides)
14
- end
15
-
16
- config.each do |k,v|
17
- acc = "#{k.to_s}=".to_sym
18
- if respond_to? acc
19
- value = v.is_a?(Hash) ? v.dup : v
20
- send(acc, value)
21
- end
22
- end
4
+ def initialize(overrides = {})
5
+ config = DEFAULTS.merge(overrides)
6
+ config.each do |k,v|
7
+ acc = "#{k.to_s}=".to_sym
8
+ self.send(acc, v) if self.respond_to? acc
9
+ end
10
+ @attribute_consuming_service = AttributeService.new
23
11
  end
24
12
 
25
- #idp data
13
+ # IdP Data
14
+ attr_accessor :idp_entity_id
26
15
  attr_accessor :idp_sso_target_url
27
- attr_accessor :idp_cert_fingerprint
28
- attr_accessor :idp_cert
29
16
  attr_accessor :idp_slo_target_url
30
- attr_accessor :idp_entity_id
31
- #sp data
32
- attr_accessor :sp_entity_id
17
+ attr_accessor :idp_cert
18
+ attr_accessor :idp_cert_fingerprint
19
+ # SP Data
20
+ attr_accessor :issuer
33
21
  attr_accessor :assertion_consumer_service_url
34
- attr_accessor :authn_context
22
+ attr_accessor :assertion_consumer_service_binding
35
23
  attr_accessor :sp_name_qualifier
36
- attr_accessor :idp_name_qualifier
37
24
  attr_accessor :name_identifier_format
38
25
  attr_accessor :name_identifier_value
39
- attr_accessor :name_identifier_value_requested
40
26
  attr_accessor :sessionindex
41
27
  attr_accessor :compress_request
42
28
  attr_accessor :compress_response
43
29
  attr_accessor :double_quote_xml_attribute_values
44
- attr_accessor :force_authn
45
30
  attr_accessor :passive
46
31
  attr_accessor :protocol_binding
32
+ attr_accessor :attributes_index
33
+ attr_accessor :force_authn
34
+ attr_accessor :security
47
35
  attr_accessor :certificate
48
36
  attr_accessor :private_key
49
- # Work-flow
50
- attr_accessor :security
37
+ attr_accessor :authn_context
38
+ attr_accessor :authn_context_comparison
39
+ attr_accessor :authn_context_decl_ref
40
+ attr_reader :attribute_consuming_service
51
41
  # Compability
52
- attr_accessor :issuer
53
42
  attr_accessor :assertion_consumer_logout_service_url
54
43
  attr_accessor :assertion_consumer_logout_service_binding
55
44
 
56
- # @return [String] SP Entity ID
57
- #
58
- def sp_entity_id
59
- val = nil
60
- if @sp_entity_id.nil?
61
- if @issuer
62
- val = @issuer
63
- end
64
- else
65
- val = @sp_entity_id
66
- end
67
- val
68
- end
69
-
70
- # Setter for SP Entity ID.
71
- # @param val [String].
72
- #
73
- def sp_entity_id=(val)
74
- @sp_entity_id = val
75
- end
76
-
77
- # @return [String] Single Logout Service URL.
78
- #
79
- def single_logout_service_url
45
+ def single_logout_service_url()
80
46
  val = nil
81
47
  if @single_logout_service_url.nil?
82
48
  if @assertion_consumer_logout_service_url
@@ -88,16 +54,12 @@ module OneLogin
88
54
  val
89
55
  end
90
56
 
91
- # Setter for the Single Logout Service URL.
92
- # @param url [String].
93
- #
94
- def single_logout_service_url=(url)
95
- @single_logout_service_url = url
57
+ # setter
58
+ def single_logout_service_url=(val)
59
+ @single_logout_service_url = val
96
60
  end
97
61
 
98
- # @return [String] Single Logout Service Binding.
99
- #
100
- def single_logout_service_binding
62
+ def single_logout_service_binding()
101
63
  val = nil
102
64
  if @single_logout_service_binding.nil?
103
65
  if @assertion_consumer_logout_service_binding
@@ -109,76 +71,46 @@ module OneLogin
109
71
  val
110
72
  end
111
73
 
112
- # Setter for Single Logout Service Binding.
113
- #
114
- # (Currently we only support "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect")
115
- # @param url [String]
116
- #
117
- def single_logout_service_binding=(url)
118
- @single_logout_service_binding = url
119
- end
120
-
121
- # Calculates the fingerprint of the IdP x509 certificate.
122
- # @return [String] The fingerprint
123
- #
124
- def get_fingerprint
125
- idp_cert_fingerprint || begin
126
- idp_cert = get_idp_cert
127
- if idp_cert
128
- Digest::SHA1.hexdigest(idp_cert.to_der).upcase.scan(/../).join(":")
129
- end
130
- end
74
+ # setter
75
+ def single_logout_service_binding=(val)
76
+ @single_logout_service_binding = val
131
77
  end
132
78
 
133
- # @return [OpenSSL::X509::Certificate|nil] Build the IdP certificate from the settings (previously format it)
134
- #
135
- def get_idp_cert
136
- return nil if idp_cert.nil?
137
-
138
- if idp_cert.respond_to?(:to_pem)
139
- idp_cert
140
- else
141
- return nil if idp_cert.empty?
142
- formatted_cert = OneLogin::RubySaml::Utils.format_cert(idp_cert)
143
- OpenSSL::X509::Certificate.new(formatted_cert)
144
- end
145
- end
146
-
147
- # @return [OpenSSL::X509::Certificate|nil] Build the SP certificate from the settings (previously format it)
148
- #
149
79
  def get_sp_cert
150
- return nil if certificate.nil? || certificate.empty?
151
-
152
- formatted_cert = OneLogin::RubySaml::Utils.format_cert(certificate)
153
- OpenSSL::X509::Certificate.new(formatted_cert)
80
+ cert = nil
81
+ if self.certificate
82
+ formated_cert = OneLogin::RubySaml::Utils.format_cert(self.certificate)
83
+ cert = OpenSSL::X509::Certificate.new(formated_cert)
84
+ end
85
+ cert
154
86
  end
155
87
 
156
- # @return [OpenSSL::PKey::RSA] Build the SP private from the settings (previously format it)
157
- #
158
88
  def get_sp_key
159
- return nil if private_key.nil? || private_key.empty?
160
-
161
- formatted_private_key = OneLogin::RubySaml::Utils.format_private_key(private_key)
162
- OpenSSL::PKey::RSA.new(formatted_private_key)
89
+ private_key = nil
90
+ if self.private_key
91
+ formated_private_key = OneLogin::RubySaml::Utils.format_private_key(self.private_key)
92
+ private_key = OpenSSL::PKey::RSA.new(formated_private_key)
93
+ end
94
+ private_key
163
95
  end
164
96
 
165
97
  private
166
98
 
167
99
  DEFAULTS = {
168
- :compress_request => true,
169
- :compress_response => true,
170
- :double_quote_xml_attribute_values => false,
171
- :assertion_consumer_service_binding => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST".freeze,
172
- :single_logout_service_binding => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect".freeze,
100
+ :assertion_consumer_service_binding => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
101
+ :single_logout_service_binding => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
102
+ :compress_request => true,
103
+ :compress_response => true,
173
104
  :security => {
174
- :authn_requests_signed => false,
175
- :logout_requests_signed => false,
176
- :logout_responses_signed => false,
177
- :embed_sign => false,
178
- :digest_method => XMLSecurity::Document::SHA1,
179
- :signature_method => XMLSecurity::Document::RSA_SHA1
180
- }.freeze
181
- }.freeze
105
+ :authn_requests_signed => false,
106
+ :logout_requests_signed => false,
107
+ :logout_responses_signed => false,
108
+ :embed_sign => false,
109
+ :digest_method => XMLSecurity::Document::SHA1,
110
+ :signature_method => XMLSecurity::Document::SHA1
111
+ },
112
+ :double_quote_xml_attribute_values => false,
113
+ }
182
114
  end
183
115
  end
184
116
  end
@@ -1,112 +1,66 @@
1
- require "xml_security"
2
- require "time"
1
+ require 'zlib'
2
+ require 'time'
3
+ require 'nokogiri'
3
4
 
4
5
  # Only supports SAML 2.0
5
- # SAML2 Logout Request (SLO IdP initiated, Parser)
6
6
  module OneLogin
7
7
  module RubySaml
8
- class SloLogoutrequest
9
-
10
- ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
11
- PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
12
-
13
- # OneLogin::RubySaml::Settings Toolkit settings
14
- attr_accessor :settings
15
-
16
- attr_reader :document
17
- attr_reader :request
8
+ class SloLogoutrequest < SamlMessage
18
9
  attr_reader :options
10
+ attr_reader :request
11
+ attr_reader :document
19
12
 
20
- def initialize(request, settings = nil, options = {})
13
+ def initialize(request, options = {})
21
14
  raise ArgumentError.new("Request cannot be nil") if request.nil?
22
- self.settings = settings
23
-
24
- @options = options
25
- @request = OneLogin::RubySaml::Utils.decode_raw_saml(request)
26
- @document = XMLSecurity::SignedDocument.new(@request)
15
+ @options = options
16
+ @request = decode_raw_saml(request)
17
+ @document = REXML::Document.new(@request)
27
18
  end
28
19
 
29
- def request_id
30
- @request_id ||= begin
31
- node = REXML::XPath.first(
32
- document,
33
- "/p:LogoutRequest",
34
- { "p" => PROTOCOL }
35
- )
36
- node.nil? ? nil : node.attributes['ID']
37
- end
20
+ def is_valid?
21
+ validate
38
22
  end
39
23
 
40
24
  def validate!
41
25
  validate(false)
42
26
  end
43
27
 
44
- def validate(soft = true)
45
- return false unless validate_structure(soft)
46
-
47
- valid_issuer?(soft)
48
- end
49
-
28
+ # The value of the user identifier as designated by the initialization request response
50
29
  def name_id
51
30
  @name_id ||= begin
52
31
  node = REXML::XPath.first(document, "/p:LogoutRequest/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
53
- Utils.element_text(node)
32
+ node.nil? ? nil : node.text
54
33
  end
55
34
  end
56
35
 
57
- alias_method :nameid, :name_id
58
-
59
- def name_id_format
60
- @name_id_node ||= REXML::XPath.first(document, "/p:LogoutRequest/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
61
- @name_id_format ||=
62
- if @name_id_node && @name_id_node.attribute("Format")
63
- @name_id_node.attribute("Format").value
64
- end
65
- end
66
-
67
- alias_method :nameid_format, :name_id_format
68
-
69
36
  def id
70
- @id ||= begin
71
- node = REXML::XPath.first(document, "/p:LogoutRequest", { "p" => PROTOCOL } )
72
- node.nil? ? nil : node.attributes['ID']
73
- end
37
+ return @id if @id
38
+ element = REXML::XPath.first(document, "/p:LogoutRequest", {
39
+ "p" => PROTOCOL} )
40
+ return nil if element.nil?
41
+ return element.attributes["ID"]
74
42
  end
75
43
 
76
44
  def issuer
77
45
  @issuer ||= begin
78
46
  node = REXML::XPath.first(document, "/p:LogoutRequest/a:Issuer", { "p" => PROTOCOL, "a" => ASSERTION })
79
- Utils.element_text(node)
47
+ node.nil? ? nil : node.text
80
48
  end
81
49
  end
82
50
 
83
51
  private
84
52
 
85
- def validate_structure(soft = true)
86
- Dir.chdir(File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'schemas'))) do
87
- @schema = Nokogiri::XML::Schema(IO.read('saml20protocol_schema.xsd'))
88
- @xml = Nokogiri::XML(self.document.to_s)
89
- end
90
- if soft
91
- @schema.validate(@xml).map{ return false }
92
- else
93
- @schema.validate(@xml).map{ |error| validation_error("#{error.message}\n\n#{@xml.to_s}") }
94
- end
53
+ def validate(soft = true)
54
+ valid_saml?(document, soft) && validate_request_state(soft)
95
55
  end
96
56
 
97
- def valid_issuer?(soft = true)
98
- return true if settings.nil? || settings.idp_entity_id.nil? || issuer.nil?
99
-
100
- unless OneLogin::RubySaml::Utils.uri_match?(issuer, settings.idp_entity_id)
101
- return soft ? false : validation_error("Doesn't match the issuer, expected: <#{self.settings.idp_entity_id}>, but was: <#{issuer}>")
57
+ def validate_request_state(soft = true)
58
+ if request.empty?
59
+ return soft ? false : validation_error("Blank request")
102
60
  end
103
61
  true
104
62
  end
105
63
 
106
- def validation_error(message)
107
- raise ValidationError.new(message)
108
- end
109
-
110
64
  end
111
65
  end
112
66
  end
@@ -1,70 +1,33 @@
1
- require "base64"
2
- require "zlib"
3
- require "cgi"
4
- require "onelogin/ruby-saml/utils"
5
- require "onelogin/ruby-saml/setting_error"
1
+ require "uuid"
2
+
3
+ require "onelogin/ruby-saml/logging"
6
4
 
7
5
  module OneLogin
8
6
  module RubySaml
7
+ class SloLogoutresponse < SamlMessage
9
8
 
10
- # SAML2 Logout Response (SLO SP initiated)
11
- #
12
- class SloLogoutresponse
13
-
14
- # Logout Response ID
15
- attr_accessor :uuid
9
+ attr_reader :uuid # Can be obtained if neccessary
16
10
 
17
- # Initializes the Logout Response. A SloLogoutresponse Object.
18
- # Asigns an ID, a random uuid.
19
- #
20
11
  def initialize
21
- @uuid = OneLogin::RubySaml::Utils.uuid
12
+ @uuid = "_" + UUID.new.generate
22
13
  end
23
14
 
24
- def response_id
25
- @uuid
26
- end
27
-
28
- # Creates the Logout Response string.
29
- # @param settings [OneLogin::RubySaml::Settings|nil] Toolkit settings
30
- # @param request_id [String] The ID of the LogoutRequest sent by this SP to the IdP. That ID will be placed as the InResponseTo in the logout response
31
- # @param logout_message [String] The Message to be placed as StatusMessage in the logout response
32
- # @param params [Hash] Some extra parameters to be added in the GET for example the RelayState
33
- # @param logout_status_code [String] The StatusCode to be placed as StatusMessage in the logout response
34
- # @return [String] Logout Request string that includes the SAMLRequest
35
- #
36
- def create(settings, request_id = nil, logout_message = nil, params = {}, logout_status_code = nil)
37
- params = create_params(settings, request_id, logout_message, params, logout_status_code)
15
+ def create(settings, request_id = nil, logout_message = nil, params = {})
16
+ params = create_params(settings, request_id, logout_message, params)
38
17
  params_prefix = (settings.idp_slo_target_url =~ /\?/) ? '&' : '?'
39
18
  saml_response = CGI.escape(params.delete("SAMLResponse"))
40
19
  response_params = "#{params_prefix}SAMLResponse=#{saml_response}"
41
20
  params.each_pair do |key, value|
42
21
  response_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
43
22
  end
44
- 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?
23
+
45
24
  @logout_url = settings.idp_slo_target_url + response_params
46
25
  end
47
26
 
48
- # Creates the Get parameters for the logout response.
49
- # @param settings [OneLogin::RubySaml::Settings|nil] Toolkit settings
50
- # @param request_id [String] The ID of the LogoutRequest sent by this SP to the IdP. That ID will be placed as the InResponseTo in the logout response
51
- # @param logout_message [String] The Message to be placed as StatusMessage in the logout response
52
- # @param params [Hash] Some extra parameters to be added in the GET for example the RelayState
53
- # @param logout_status_code [String] The StatusCode to be placed as StatusMessage in the logout response
54
- # @return [Hash] Parameters
55
- #
56
- def create_params(settings, request_id = nil, logout_message = nil, params = {}, logout_status_code = nil)
57
- # The method expects :RelayState but sometimes we get 'RelayState' instead.
58
- # Based on the HashWithIndifferentAccess value in Rails we could experience
59
- # conflicts so this line will solve them.
60
- relay_state = params[:RelayState] || params['RelayState']
61
-
62
- if relay_state.nil?
63
- params.delete(:RelayState)
64
- params.delete('RelayState')
65
- end
27
+ def create_params(settings, request_id = nil, logout_message = nil, params = {})
28
+ params = {} if params.nil?
66
29
 
67
- response_doc = create_logout_response_xml_doc(settings, request_id, logout_message, logout_status_code)
30
+ response_doc = create_logout_response_xml_doc(settings, request_id, logout_message)
68
31
  response_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values
69
32
 
70
33
  response = ""
@@ -72,29 +35,18 @@ module OneLogin
72
35
 
73
36
  Logging.debug "Created SLO Logout Response: #{response}"
74
37
 
75
- response = Zlib::Deflate.deflate(response, 9)[2..-5] if settings.compress_response
76
- if Base64.respond_to?('strict_encode64')
77
- base64_response = Base64.strict_encode64(response)
78
- else
79
- base64_response = Base64.encode64(response).gsub(/\n/, "")
80
- end
38
+ response = deflate(response) if settings.compress_response
39
+ base64_response = encode(response)
81
40
  response_params = {"SAMLResponse" => base64_response}
82
41
 
83
42
  if settings.security[:logout_responses_signed] && !settings.security[:embed_sign] && settings.private_key
84
- params['SigAlg'] = settings.security[:signature_method]
85
- url_string = OneLogin::RubySaml::Utils.build_query(
86
- :type => 'SAMLResponse',
87
- :data => base64_response,
88
- :relay_state => relay_state,
89
- :sig_alg => params['SigAlg']
90
- )
91
- sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
92
- signature = settings.get_sp_key.sign(sign_algorithm.new, url_string)
93
- if Base64.respond_to?('strict_encode64')
94
- params['Signature'] = Base64.strict_encode64(signature)
95
- else
96
- params['Signature'] = Base64.encode64(signature).gsub(/\n/, "")
97
- end
43
+ params['SigAlg'] = XMLSecurity::Document::SHA1
44
+ url_string = "SAMLResponse=#{CGI.escape(base64_response)}"
45
+ url_string += "&RelayState=#{CGI.escape(params['RelayState'])}" if params['RelayState']
46
+ url_string += "&SigAlg=#{CGI.escape(params['SigAlg'])}"
47
+ private_key = settings.get_sp_key()
48
+ signature = private_key.sign(XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method]).new, url_string)
49
+ params['Signature'] = encode(signature)
98
50
  end
99
51
 
100
52
  params.each_pair do |key, value|
@@ -104,19 +56,7 @@ module OneLogin
104
56
  response_params
105
57
  end
106
58
 
107
- # Creates the SAMLResponse String.
108
- # @param settings [OneLogin::RubySaml::Settings|nil] Toolkit settings
109
- # @param request_id [String] The ID of the LogoutRequest sent by this SP to the IdP. That ID will be placed as the InResponseTo in the logout response
110
- # @param logout_message [String] The Message to be placed as StatusMessage in the logout response
111
- # @param logout_status_code [String] The StatusCode to be placed as StatusMessage in the logout response
112
- # @return [String] The SAMLResponse String.
113
- #
114
- def create_logout_response_xml_doc(settings, request_id = nil, logout_message = nil, logout_status_code = nil)
115
- document = create_xml_document(settings, request_id, logout_message, logout_status_code)
116
- sign_document(document, settings)
117
- end
118
-
119
- def create_xml_document(settings, request_id = nil, logout_message = nil, status_code = nil)
59
+ def create_logout_response_xml_doc(settings, request_id = nil, logout_message = nil)
120
60
  time = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
121
61
 
122
62
  response_doc = XMLSecurity::Document.new
@@ -127,38 +67,33 @@ module OneLogin
127
67
  root.attributes['IssueInstant'] = time
128
68
  root.attributes['Version'] = '2.0'
129
69
  root.attributes['InResponseTo'] = request_id unless request_id.nil?
130
- root.attributes['Destination'] = settings.idp_slo_target_url unless settings.idp_slo_target_url.nil? or settings.idp_slo_target_url.empty?
70
+ root.attributes['Destination'] = settings.idp_slo_target_url unless settings.idp_slo_target_url.nil?
131
71
 
132
- if settings.sp_entity_id != nil
133
- issuer = root.add_element "saml:Issuer"
134
- issuer.text = settings.sp_entity_id
135
- end
136
-
137
- # add status
72
+ # add success message
138
73
  status = root.add_element 'samlp:Status'
139
74
 
140
- # status code
141
- status_code ||= 'urn:oasis:names:tc:SAML:2.0:status:Success'
142
- status_code_elem = status.add_element 'samlp:StatusCode'
143
- status_code_elem.attributes['Value'] = status_code
75
+ # success status code
76
+ status_code = status.add_element 'samlp:StatusCode'
77
+ status_code.attributes['Value'] = 'urn:oasis:names:tc:SAML:2.0:status:Success'
144
78
 
145
- # status message
79
+ # success status message
146
80
  logout_message ||= 'Successfully Signed Out'
147
81
  status_message = status.add_element 'samlp:StatusMessage'
148
82
  status_message.text = logout_message
149
83
 
150
- response_doc
151
- end
84
+ if settings.issuer != nil
85
+ issuer = root.add_element "saml:Issuer"
86
+ issuer.text = settings.issuer
87
+ end
152
88
 
153
- def sign_document(document, settings)
154
- # embed signature
89
+ # embebed sign
155
90
  if settings.security[:logout_responses_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
156
- private_key = settings.get_sp_key
157
- cert = settings.get_sp_cert
158
- document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
91
+ private_key = settings.get_sp_key()
92
+ cert = settings.get_sp_cert()
93
+ response_doc.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
159
94
  end
160
95
 
161
- document
96
+ response_doc
162
97
  end
163
98
 
164
99
  end