ruby-saml 0.7.2 → 0.7.3

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.

data/.gitignore CHANGED
@@ -9,3 +9,4 @@ lib/Lib.iml
9
9
  test/Test.iml
10
10
  .rvmrc
11
11
  *.gem
12
+ .bundle
data/Gemfile CHANGED
@@ -4,10 +4,12 @@ gemspec
4
4
 
5
5
  group :test do
6
6
  gem "ruby-debug", "~> 0.10.4", :require => nil, :platforms => :ruby_18
7
- gem "debugger", "~> 1.1.1", :require => nil, :platforms => :ruby_19
8
- gem "shoulda"
9
- gem "rake"
10
- gem "mocha"
11
- gem "nokogiri"
12
- gem "timecop"
7
+ gem "debugger", "~> 1.1", :require => nil, :platforms => :ruby_19
8
+ gem "shoulda", "~> 2.11"
9
+ gem "rake", "~> 10"
10
+ gem "mocha", "~> 0.14"
11
+ gem "nokogiri", "~> 1.5"
12
+ gem "timecop", "<= 0.6.0"
13
+ gem "systemu", "~> 2"
14
+ gem "rspec", "~> 2"
13
15
  end
data/README.md CHANGED
@@ -90,17 +90,19 @@ What's left at this point, is to wrap it all up in a controller and point the in
90
90
  If are using saml:AttributeStatement to transfare metadata, like the user name, you can access all the attributes through response.attributes. It
91
91
  contains all the saml:AttributeStatement with its 'Name' as a indifferent key and the one saml:AttributeValue as value.
92
92
 
93
+ ```ruby
93
94
  response = Onelogin::Saml::Response.new(params[:SAMLResponse])
94
95
  response.settings = saml_settings
95
96
 
96
97
  response.attributes[:username]
98
+ ```
97
99
 
98
100
  ## Service Provider Metadata
99
101
 
100
102
  To form a trusted pair relationship with the IdP, the SP (you) need to provide metadata XML
101
- to the IdP for various good reasons. (Caching, certificate lookups, relying party permissions, etc)
103
+ to the IdP for various good reasons. (Caching, certificate lookups, relaying party permissions, etc)
102
104
 
103
- The class Onelogin::Saml::Metdata takes care of this by reading the Settings and returning XML. All
105
+ The class Onelogin::Saml::Metadata takes care of this by reading the Settings and returning XML. All
104
106
  you have to do is add a controller to return the data, then give this URL to the IdP administrator.
105
107
  The metdata will be polled by the IdP every few minutes, so updating your settings should propagate
106
108
  to the IdP settings.
@@ -116,6 +118,20 @@ to the IdP settings.
116
118
  end
117
119
  ```
118
120
 
121
+ ## Clock Drift
122
+
123
+ Server clocks tend to drift naturally. If during validation of the response you get the error "Current time is earlier than NotBefore condition" then this may be due to clock differences between your system and that of the Identity Provider.
124
+
125
+ First, ensure that both systems synchronize their clocks, using for example the industry standard [Network Time Protocol (NTP)](http://en.wikipedia.org/wiki/Network_Time_Protocol).
126
+
127
+ Even then you may experience intermittent issues though, because the clock of the Identity Provider may drift slightly ahead of your system clocks. To allow for a small amount of clock drift you can initialize the response passing in an option named `:allowed_clock_drift`. Its value must be given in a number (and/or fraction) of seconds. The value given is added to the current time at which the response is validated before it's tested against the `NotBefore` assertion. For example:
128
+
129
+ ```ruby
130
+ response = Onelogin::Saml::Response.new(params[:SAMLResponse], :allowed_clock_drift => 1)
131
+ ```
132
+
133
+ Make sure to keep the value as comfortably small as possible to keep security risks to a minimum.
134
+
119
135
  ## Note on Patches/Pull Requests
120
136
 
121
137
  * Fork the project.
@@ -13,6 +13,7 @@ module Onelogin
13
13
  params = {} if params.nil?
14
14
 
15
15
  request_doc = create_authentication_xml_doc(settings)
16
+ request_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values
16
17
 
17
18
  request = ""
18
19
  request_doc.write(request)
@@ -35,7 +36,7 @@ module Onelogin
35
36
  def create_authentication_xml_doc(settings)
36
37
  uuid = "_" + UUID.new.generate
37
38
  time = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
38
- # Create AuthnRequest root element using REXML
39
+ # Create AuthnRequest root element using REXML
39
40
  request_doc = REXML::Document.new
40
41
 
41
42
  root = request_doc.add_element "samlp:AuthnRequest", { "xmlns:samlp" => "urn:oasis:names:tc:SAML:2.0:protocol" }
@@ -43,6 +44,8 @@ module Onelogin
43
44
  root.attributes['IssueInstant'] = time
44
45
  root.attributes['Version'] = "2.0"
45
46
  root.attributes['Destination'] = settings.idp_sso_target_url unless settings.idp_sso_target_url.nil?
47
+ root.attributes['IsPassive'] = settings.passive unless settings.passive.nil?
48
+ root.attributes['ProtocolBinding'] = settings.protocol_binding unless settings.protocol_binding.nil?
46
49
 
47
50
  # Conditionally defined elements based on settings
48
51
  if settings.assertion_consumer_service_url != nil
@@ -53,7 +56,7 @@ module Onelogin
53
56
  issuer.text = settings.issuer
54
57
  end
55
58
  if settings.name_identifier_format != nil
56
- root.add_element "samlp:NameIDPolicy", {
59
+ root.add_element "samlp:NameIDPolicy", {
57
60
  "xmlns:samlp" => "urn:oasis:names:tc:SAML:2.0:protocol",
58
61
  # Might want to make AllowCreate a setting?
59
62
  "AllowCreate" => "true",
@@ -62,14 +65,14 @@ module Onelogin
62
65
  end
63
66
 
64
67
  # BUG fix here -- if an authn_context is defined, add the tags with an "exact"
65
- # match required for authentication to succeed. If this is not defined,
68
+ # match required for authentication to succeed. If this is not defined,
66
69
  # the IdP will choose default rules for authentication. (Shibboleth IdP)
67
70
  if settings.authn_context != nil
68
- requested_context = root.add_element "samlp:RequestedAuthnContext", {
71
+ requested_context = root.add_element "samlp:RequestedAuthnContext", {
69
72
  "xmlns:samlp" => "urn:oasis:names:tc:SAML:2.0:protocol",
70
73
  "Comparison" => "exact",
71
74
  }
72
- class_ref = requested_context.add_element "saml:AuthnContextClassRef", {
75
+ class_ref = requested_context.add_element "saml:AuthnContextClassRef", {
73
76
  "xmlns:saml" => "urn:oasis:names:tc:SAML:2.0:assertion",
74
77
  }
75
78
  class_ref.text = settings.authn_context
@@ -105,7 +105,7 @@ module Onelogin
105
105
  if soft
106
106
  @schema.validate(@xml).map{ return false }
107
107
  else
108
- @schema.validate(@xml).map{ |error| raise(Exception.new("#{error.message}\n\n#{@xml.to_s}")) }
108
+ @schema.validate(@xml).map{ |error| validation_error("#{error.message}\n\n#{@xml.to_s}") }
109
109
  end
110
110
  end
111
111
 
@@ -151,4 +151,4 @@ module Onelogin
151
151
  end
152
152
  end
153
153
  end
154
- end
154
+ end
@@ -78,7 +78,7 @@ module Onelogin
78
78
  parse_time(node, "SessionNotOnOrAfter")
79
79
  end
80
80
  end
81
-
81
+
82
82
  # Checks the status of the response for a "Success" code
83
83
  def success?
84
84
  @status_code ||= begin
@@ -92,6 +92,14 @@ module Onelogin
92
92
  @conditions ||= xpath_first_from_signed_assertion('/a:Conditions')
93
93
  end
94
94
 
95
+ def not_before
96
+ @not_before ||= parse_time(conditions, "NotBefore")
97
+ end
98
+
99
+ def not_on_or_after
100
+ @not_on_or_after ||= parse_time(conditions, "NotOnOrAfter")
101
+ end
102
+
95
103
  def issuer
96
104
  @issuer ||= begin
97
105
  node = REXML::XPath.first(document, "/p:Response/a:Issuer", { "p" => PROTOCOL, "a" => ASSERTION })
@@ -110,7 +118,7 @@ module Onelogin
110
118
  validate_structure(soft) &&
111
119
  validate_response_state(soft) &&
112
120
  validate_conditions(soft) &&
113
- document.validate(get_fingerprint, soft) &&
121
+ document.validate_document(get_fingerprint, soft) &&
114
122
  success?
115
123
  end
116
124
 
@@ -161,16 +169,14 @@ module Onelogin
161
169
  return true if conditions.nil?
162
170
  return true if options[:skip_conditions]
163
171
 
164
- if (not_before = parse_time(conditions, "NotBefore"))
165
- if Time.now.utc < not_before
166
- return soft ? false : validation_error("Current time is earlier than NotBefore condition")
167
- end
172
+ now = Time.now.utc
173
+
174
+ if not_before && (now + (options[:allowed_clock_drift] || 0)) < not_before
175
+ return soft ? false : validation_error("Current time is earlier than NotBefore condition")
168
176
  end
169
177
 
170
- if (not_on_or_after = parse_time(conditions, "NotOnOrAfter"))
171
- if Time.now.utc >= not_on_or_after
172
- return soft ? false : validation_error("Current time is on or after NotOnOrAfter condition")
173
- end
178
+ if not_on_or_after && now >= not_on_or_after
179
+ return soft ? false : validation_error("Current time is on or after NotOnOrAfter condition")
174
180
  end
175
181
 
176
182
  true
@@ -16,10 +16,13 @@ module Onelogin
16
16
  attr_accessor :sessionindex
17
17
  attr_accessor :assertion_consumer_logout_service_url
18
18
  attr_accessor :compress_request
19
+ attr_accessor :double_quote_xml_attribute_values
20
+ attr_accessor :passive
21
+ attr_accessor :protocol_binding
19
22
 
20
23
  private
21
-
22
- DEFAULTS = {:compress_request => true}
24
+
25
+ DEFAULTS = {:compress_request => true, :double_quote_xml_attribute_values => false}
23
26
  end
24
27
  end
25
28
  end
@@ -1,6 +1,6 @@
1
1
  module Onelogin
2
2
  module Saml
3
- class ValidationError < Exception
3
+ class ValidationError < StandardError
4
4
  end
5
5
  end
6
6
  end
@@ -1,5 +1,5 @@
1
1
  module Onelogin
2
2
  module Saml
3
- VERSION = '0.7.2'
3
+ VERSION = '0.7.3'
4
4
  end
5
5
  end
@@ -44,9 +44,10 @@ module XMLSecurity
44
44
  extract_signed_element_id
45
45
  end
46
46
 
47
- def validate(idp_cert_fingerprint, soft = true)
47
+ def validate_document(idp_cert_fingerprint, soft = true)
48
48
  # get cert from response
49
49
  cert_element = REXML::XPath.first(self, "//ds:X509Certificate", { "ds"=>DSIG })
50
+ raise Onelogin::Saml::ValidationError.new("Certificate element missing in response (ds:X509Certificate)") unless cert_element
50
51
  base64_cert = cert_element.text
51
52
  cert_text = Base64.decode64(base64_cert)
52
53
  cert = OpenSSL::X509::Certificate.new(cert_text)
@@ -58,10 +59,10 @@ module XMLSecurity
58
59
  return soft ? false : (raise Onelogin::Saml::ValidationError.new("Fingerprint mismatch"))
59
60
  end
60
61
 
61
- validate_doc(base64_cert, soft)
62
+ validate_signature(base64_cert, soft)
62
63
  end
63
64
 
64
- def validate_doc(base64_cert, soft = true)
65
+ def validate_signature(base64_cert, soft = true)
65
66
  # validate references
66
67
 
67
68
  # check for inclusive namespaces
@@ -93,7 +94,7 @@ module XMLSecurity
93
94
 
94
95
  hashed_element = document.at_xpath("//*[@ID='#{uri[1..-1]}']")
95
96
  canon_algorithm = canon_algorithm REXML::XPath.first(ref, '//ds:CanonicalizationMethod', 'ds' => DSIG)
96
- canon_hashed_element = hashed_element.canonicalize(canon_algorithm, inclusive_namespaces).gsub('&','&amp;')
97
+ canon_hashed_element = hashed_element.canonicalize(canon_algorithm, inclusive_namespaces)
97
98
 
98
99
  digest_algorithm = algorithm(REXML::XPath.first(ref, "//ds:DigestMethod"))
99
100
 
@@ -25,5 +25,5 @@ Gem::Specification.new do |s|
25
25
 
26
26
  s.add_runtime_dependency("canonix", ["0.1.1"])
27
27
  s.add_runtime_dependency("uuid", ["~> 2.3"])
28
- s.add_runtime_dependency("nokogiri")
28
+ s.add_runtime_dependency("nokogiri", ["~> 1.5.0"])
29
29
  end
@@ -0,0 +1 @@
1
+ MIIEYTCCA0mgAwIBAgIJAMax+2BoUJmCMA0GCSqGSIb3DQEBBQUAMIHGMQswCQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xIzAhBgNVBAoMGldlbGxzcHJpbmcgV29ybGR3aWRlLCBJbmMuMRwwGgYDVQQLDBNTeXN0ZW1zIEVuZ2luZWVyaW5nMSQwIgYDVQQDDBtzc28ud2VsbHNwcmluZ3dvcmxkd2lkZS5jb20xKTAnBgkqhkiG9w0BCQEWGml0QHdlbGxzcHJpbmd3b3JsZHdpZGUuY29tMB4XDTEzMDIyNzIzNTUwOFoXDTIzMDIyNzIzNTUwOFowgcYxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEjMCEGA1UECgwaV2VsbHNwcmluZyBXb3JsZHdpZGUsIEluYy4xHDAaBgNVBAsME1N5c3RlbXMgRW5naW5lZXJpbmcxJDAiBgNVBAMMG3Nzby53ZWxsc3ByaW5nd29ybGR3aWRlLmNvbTEpMCcGCSqGSIb3DQEJARYaaXRAd2VsbHNwcmluZ3dvcmxkd2lkZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzNhrDaXa00JAIRaxEyDrK/Zjj8bBTQD5dPgugDndYf1AOpzSGpGFU+lPu0QRv0o66K64HrF24FATWI18Q6aZ+xX8QbuBrfia6hOFef29Sk5paS9+DcDCmisuNpl84kbbiazy6S6cFtcdrG9/cr2iXtYmIzz7EfUcP/UVAp24ZW7dWhcvxoqxF9n6Fj94N+rA0dmUFUGz6glm7us3p36xbkiUMpgr3feD/9P34H+2YFsQ2b2DblDI5Z7YULHxBsl5nuhPLFuPN1olcWQBsJYO6iHElFRH+487L2yZ1mLVXKI0LFb/w1rAJpPeUc8E5s1MATAjNx3wPwwqgw30sKtoXAgMBAAGjUDBOMB0GA1UdDgQWBBSrGGV9w3hGXTafkJLUaWBsWiDGaTAfBgNVHSMEGDAWgBSrGGV9w3hGXTafkJLUaWBsWiDGaTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCcvZV0VIwIRD4C5CItFwfNRF2LRBmYiNh4FJbo0wESbH0cWT9vXNdcjcx6PHrIj7ICErSCR5eZmIrSgLEBEkptjVsiFsHWSvMHv37WaHwyhZWnhutss32aP9+ifxQ1lzwm54jZWZsVVVFQH155BDsVeU1UwEhvcCExFa7RNjyvqQrZmyQwMFSzL1cQp0humu0hHLtAI7E32lp5itw6kTOfyhjB8d1bzBVZe6RY64RxOPEcx+9hkrHmfCohdt644jRtPdLTvqqxpscYGD+L2QOt1HpbGgAdcgUZeUHo/eosqpwDOoyuFepz7JzqMncxFN//NmjnFGVZdGR+6bTxKUKq
@@ -102,7 +102,7 @@ class RubySamlTest < Test::Unit::TestCase
102
102
  should "raise error for invalid xml" do
103
103
  logoutresponse = Onelogin::Saml::Logoutresponse.new(invalid_xml_response, settings)
104
104
 
105
- assert_raises(Exception) { logoutresponse.validate! }
105
+ assert_raises(Onelogin::Saml::ValidationError) { logoutresponse.validate! }
106
106
  end
107
107
  end
108
108
 
@@ -46,6 +46,23 @@ class RequestTest < Test::Unit::TestCase
46
46
  assert_match /^<samlp:AuthnRequest/, decoded
47
47
  end
48
48
 
49
+ should "create the SAMLRequest URL parameter with IsPassive" do
50
+ settings = Onelogin::Saml::Settings.new
51
+ settings.idp_sso_target_url = "http://example.com"
52
+ settings.passive = true
53
+ auth_url = Onelogin::Saml::Authrequest.new.create(settings)
54
+ assert auth_url =~ /^http:\/\/example\.com\?SAMLRequest=/
55
+ payload = CGI.unescape(auth_url.split("=").last)
56
+ decoded = Base64.decode64(payload)
57
+
58
+ zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
59
+ inflated = zstream.inflate(decoded)
60
+ zstream.finish
61
+ zstream.close
62
+
63
+ assert_match /<samlp:AuthnRequest[^<]* IsPassive='true'/, inflated
64
+ end
65
+
49
66
  should "accept extra parameters" do
50
67
  settings = Onelogin::Saml::Settings.new
51
68
  settings.idp_sso_target_url = "http://example.com"
@@ -120,7 +120,7 @@ class RubySamlTest < Test::Unit::TestCase
120
120
  settings = Onelogin::Saml::Settings.new
121
121
  response.settings = settings
122
122
  settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
123
- XMLSecurity::SignedDocument.any_instance.expects(:validate_doc).returns(true)
123
+ XMLSecurity::SignedDocument.any_instance.expects(:validate_signature).returns(true)
124
124
  assert response.validate!
125
125
  end
126
126
 
@@ -133,6 +133,15 @@ class RubySamlTest < Test::Unit::TestCase
133
133
  assert response.validate!
134
134
  end
135
135
 
136
+ should "validate the digest" do
137
+ response = Onelogin::Saml::Response.new(r1_response_document_6)
138
+ response.stubs(:conditions).returns(nil)
139
+ settings = Onelogin::Saml::Settings.new
140
+ settings.idp_cert = Base64.decode64(r1_signature_2)
141
+ response.settings = settings
142
+ assert response.validate!
143
+ end
144
+
136
145
  should "validate SAML 2.0 XML structure" do
137
146
  resp_xml = Base64.decode64(response_document_4).gsub(/emailAddress/,'test')
138
147
  response = Onelogin::Saml::Response.new(Base64.encode64(resp_xml))
@@ -175,6 +184,17 @@ class RubySamlTest < Test::Unit::TestCase
175
184
  response = Onelogin::Saml::Response.new(response_document_5)
176
185
  assert response.send(:validate_conditions, true)
177
186
  end
187
+
188
+ should "optionally allow for clock drift" do
189
+ # The NotBefore condition in the document is 2011-06-14T18:21:01.516Z
190
+ Time.stubs(:now).returns(Time.parse("2011-06-14T18:21:01Z"))
191
+ response = Onelogin::Saml::Response.new(response_document_5, :allowed_clock_drift => 0.515)
192
+ assert !response.send(:validate_conditions, true)
193
+
194
+ Time.stubs(:now).returns(Time.parse("2011-06-14T18:21:01Z"))
195
+ response = Onelogin::Saml::Response.new(response_document_5, :allowed_clock_drift => 0.516)
196
+ assert response.send(:validate_conditions, true)
197
+ end
178
198
  end
179
199
 
180
200
  context "#attributes" do
@@ -220,13 +240,13 @@ class RubySamlTest < Test::Unit::TestCase
220
240
  response = Onelogin::Saml::Response.new(response_document)
221
241
  assert_equal "https://app.onelogin.com/saml/metadata/13590", response.issuer
222
242
  end
223
-
243
+
224
244
  should "return the issuer inside the response" do
225
245
  response = Onelogin::Saml::Response.new(response_document_2)
226
246
  assert_equal "wibble", response.issuer
227
247
  end
228
248
  end
229
-
249
+
230
250
  context "#success" do
231
251
  should "find a status code that says success" do
232
252
  response = Onelogin::Saml::Response.new(response_document)
@@ -0,0 +1 @@
1
+ PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIElEPSJfNmMxZmY2ZmIwNDhjODcyYjdjYmQxNDU2NjA3NGYxN2JlOGQ5YzcyODM3IiBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAxMy0wMy0yNVQxNTozNjowMFoiIERlc3RpbmF0aW9uPSJodHRwczovL3JwbS5uZXdyZWxpYy5jb20vYWNjb3VudHMvMTM2ODU3L3Nzby9zYW1sL2ZpbmFsaXplIiBJblJlc3BvbnNlVG89Il85ZTFmMzVkMC03NzhmLTAxMzAtMWRhOS0wNDJiMmI0ZmQyNjUiPjxzYW1sOklzc3Vlcj5odHRwczovL3Nzby53ZWxsc3ByaW5nd29ybGR3aWRlLmNvbS9zaW1wbGVzYW1sL3NhbWwyL2lkcC9tZXRhZGF0YS5waHA8L3NhbWw6SXNzdWVyPjxzYW1scDpTdGF0dXM+PHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbHA6U3RhdHVzPjxzYW1sOkFzc2VydGlvbiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIElEPSJfMDMwNTgzYjVkN2FhOWY4ODQzODg2NmZhNjE2NDBhMzdjMzVlNGZkNjQ3IiBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAxMy0wMy0yNVQxNTozNjowMFoiPjxzYW1sOklzc3Vlcj5odHRwczovL3Nzby53ZWxsc3ByaW5nd29ybGR3aWRlLmNvbS9zaW1wbGVzYW1sL3NhbWwyL2lkcC9tZXRhZGF0YS5waHA8L3NhbWw6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPgogIDxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+CiAgICA8ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3JzYS1zaGExIi8+CiAgPGRzOlJlZmVyZW5jZSBVUkk9IiNfMDMwNTgzYjVkN2FhOWY4ODQzODg2NmZhNjE2NDBhMzdjMzVlNGZkNjQ3Ij48ZHM6VHJhbnNmb3Jtcz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjc2hhMSIvPjxkczpEaWdlc3RWYWx1ZT50bjc3ajFjMUQ0SjdPaTNrNVZVWlI2YjlzZTQ9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8+PGRzOlNpZ25hdHVyZVZhbHVlPldCQ2lWUUM2ZWFscGlzT3NYUUxOaGFIb3ptRy9CWGsxb3lFd2EyVnVBQ2FjTGlSMFplRk9ScXNzQW1tWkVPZXVlSXd1TEUxLzhPZ0t6OUZFYWZrREh6blh4c0x1dXg1N1pPS2R5cTJtUXllNS9XV2NPRVJtYVFHeE5EeERUVzdod1BVUDFLRzJNMTZvbTlzc3RmNTNTSTRHYkg0MzRnM3BwNGlQMjlLVis4b0t6V1h3VUtQb0FkUTFpT2pENWNITXhmNU9oQXRsQ1h6b0JtYTV3K3lOcmgvWFVBMmE2am1ubXV2cWdPS2VUU3VzWWlLYlVIVTAxOE15cVFrcmJaTXFndC9SMTY2RWxVU3RzcFlKc0tYalpYN1hLOUQ4ekdNNWZhQVErZ3BReW1BVEFrRE84MGsrVXZQdjhxWUhXemdvRCtSaDJFNjJpMzdkODZkUjNUNEdOUT09PC9kczpTaWduYXR1cmVWYWx1ZT4KPGRzOktleUluZm8+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJRVlUQ0NBMG1nQXdJQkFnSUpBTWF4KzJCb1VKbUNNQTBHQ1NxR1NJYjNEUUVCQlFVQU1JSEdNUXN3Q1FZRFZRUUdFd0pWVXpFUk1BOEdBMVVFQ0F3SVNXeHNhVzV2YVhNeEVEQU9CZ05WQkFjTUIwTm9hV05oWjI4eEl6QWhCZ05WQkFvTUdsZGxiR3h6Y0hKcGJtY2dWMjl5YkdSM2FXUmxMQ0JKYm1NdU1Sd3dHZ1lEVlFRTERCTlRlWE4wWlcxeklFVnVaMmx1WldWeWFXNW5NU1F3SWdZRFZRUUREQnR6YzI4dWQyVnNiSE53Y21sdVozZHZjbXhrZDJsa1pTNWpiMjB4S1RBbkJna3Foa2lHOXcwQkNRRVdHbWwwUUhkbGJHeHpjSEpwYm1kM2IzSnNaSGRwWkdVdVkyOXRNQjRYRFRFek1ESXlOekl6TlRVd09Gb1hEVEl6TURJeU56SXpOVFV3T0Zvd2djWXhDekFKQmdOVkJBWVRBbFZUTVJFd0R3WURWUVFJREFoSmJHeHBibTlwY3pFUU1BNEdBMVVFQnd3SFEyaHBZMkZuYnpFak1DRUdBMVVFQ2d3YVYyVnNiSE53Y21sdVp5QlhiM0pzWkhkcFpHVXNJRWx1WXk0eEhEQWFCZ05WQkFzTUUxTjVjM1JsYlhNZ1JXNW5hVzVsWlhKcGJtY3hKREFpQmdOVkJBTU1HM056Ynk1M1pXeHNjM0J5YVc1bmQyOXliR1IzYVdSbExtTnZiVEVwTUNjR0NTcUdTSWIzRFFFSkFSWWFhWFJBZDJWc2JITndjbWx1WjNkdmNteGtkMmxrWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDek5ockRhWGEwMEpBSVJheEV5RHJLL1pqajhiQlRRRDVkUGd1Z0RuZFlmMUFPcHpTR3BHRlUrbFB1MFFSdjBvNjZLNjRIckYyNEZBVFdJMThRNmFaK3hYOFFidUJyZmlhNmhPRmVmMjlTazVwYVM5K0RjRENtaXN1TnBsODRrYmJpYXp5NlM2Y0Z0Y2RyRzkvY3IyaVh0WW1Jeno3RWZVY1AvVVZBcDI0Wlc3ZFdoY3Z4b3F4RjluNkZqOTROK3JBMGRtVUZVR3o2Z2xtN3VzM3AzNnhia2lVTXBncjNmZUQvOVAzNEgrMllGc1EyYjJEYmxESTVaN1lVTEh4QnNsNW51aFBMRnVQTjFvbGNXUUJzSllPNmlIRWxGUkgrNDg3TDJ5WjFtTFZYS0kwTEZiL3cxckFKcFBlVWM4RTVzMU1BVEFqTngzd1B3d3FndzMwc0t0b1hBZ01CQUFHalVEQk9NQjBHQTFVZERnUVdCQlNyR0dWOXczaEdYVGFma0pMVWFXQnNXaURHYVRBZkJnTlZIU01FR0RBV2dCU3JHR1Y5dzNoR1hUYWZrSkxVYVdCc1dpREdhVEFNQmdOVkhSTUVCVEFEQVFIL01BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2N2WlYwVkl3SVJENEM1Q0l0RndmTlJGMkxSQm1ZaU5oNEZKYm8wd0VTYkgwY1dUOXZYTmRjamN4NlBIcklqN0lDRXJTQ1I1ZVptSXJTZ0xFQkVrcHRqVnNpRnNIV1N2TUh2MzdXYUh3eWhaV25odXRzczMyYVA5K2lmeFExbHp3bTU0alpXWnNWVlZGUUgxNTVCRHNWZVUxVXdFaHZjQ0V4RmE3Uk5qeXZxUXJabXlRd01GU3pMMWNRcDBodW11MGhITHRBSTdFMzJscDVpdHc2a1RPZnloakI4ZDFiekJWWmU2Ulk2NFJ4T1BFY3grOWhrckhtZkNvaGR0NjQ0alJ0UGRMVHZxcXhwc2NZR0QrTDJRT3QxSHBiR2dBZGNnVVplVUhvL2Vvc3Fwd0RPb3l1RmVwejdKenFNbmN4Rk4vL05tam5GR1ZaZEdSKzZiVHhLVUtxPC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+PHNhbWw6U3ViamVjdD48c2FtbDpOYW1lSUQgU1BOYW1lUXVhbGlmaWVyPSJycG0ubmV3cmVsaWMuY29tIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI+ZTQwYzA4OTA3NDVjZTkyNTBhZDIyM2I1OTA5MGNjNmRjNWQxZjVhMTwvc2FtbDpOYW1lSUQ+PHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPjxzYW1sOlN1YmplY3RDb25maXJtYXRpb25EYXRhIE5vdE9uT3JBZnRlcj0iMjAxMy0wMy0yNVQxNTo0MTowMFoiIFJlY2lwaWVudD0iaHR0cHM6Ly9ycG0ubmV3cmVsaWMuY29tL2FjY291bnRzLzEzNjg1Ny9zc28vc2FtbC9maW5hbGl6ZSIgSW5SZXNwb25zZVRvPSJfOWUxZjM1ZDAtNzc4Zi0wMTMwLTFkYTktMDQyYjJiNGZkMjY1Ii8+PC9zYW1sOlN1YmplY3RDb25maXJtYXRpb24+PC9zYW1sOlN1YmplY3Q+PHNhbWw6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMTMtMDMtMjVUMTU6MzU6MzBaIiBOb3RPbk9yQWZ0ZXI9IjIwMTMtMDMtMjVUMTU6NDE6MDBaIj48c2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjxzYW1sOkF1ZGllbmNlPnJwbS5uZXdyZWxpYy5jb208L3NhbWw6QXVkaWVuY2U+PC9zYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+PC9zYW1sOkNvbmRpdGlvbnM+PHNhbWw6QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDEzLTAzLTI1VDE1OjIwOjEyWiIgU2Vzc2lvbk5vdE9uT3JBZnRlcj0iMjAxMy0wMy0yNVQyMzozNjowMFoiIFNlc3Npb25JbmRleD0iX2ZmNjc4NWJkNTUxYjQ2NzVjMGI2MGI3ZTI2YzFmYmI3Y2Y1MDljZTk5OSI+PHNhbWw6QXV0aG5Db250ZXh0PjxzYW1sOkF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOlBhc3N3b3JkPC9zYW1sOkF1dGhuQ29udGV4dENsYXNzUmVmPjwvc2FtbDpBdXRobkNvbnRleHQ+PC9zYW1sOkF1dGhuU3RhdGVtZW50PjxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD48c2FtbDpBdHRyaWJ1dGUgTmFtZT0iaG9tZURpcmVjdG9yeSIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpzdHJpbmciPi9ob21lL2t5bGUuYmFjenluc2tpPC9zYW1sOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDpBdHRyaWJ1dGU+PHNhbWw6QXR0cmlidXRlIE5hbWU9ImdpZE51bWJlciIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpzdHJpbmciPjEwNDc8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0idWlkTnVtYmVyIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+MTA0Nzwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJzc2hQdWJsaWNLZXkiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5zc2gtcnNhIEFBQUFCM056YUMxeWMyRUFBQUFEQVFBQkFBQUJBUUMrL3U1N2tqOWNRVXNXcW5EOVNYY0lNcCsyUDF3aFREa2FHZ2RPVUtySHpNWmxPMEdrTk9oZFZralBGeFJrcGZZWk1sMldZZE9OQkNiK1ZmY3pyd3J6NFNjOHIvaFFkQUdpRWJEYzJLRHZkT1dSYkRGZGlSVThYNy93aFppOE1ibUx1ZmN1cmlRQmZ3ekpET2NiY2c4S0ZvN25GR3JoNmwrWmVzZ2lZWC9CV2daYmp0NFR4aHhRWHpCWDJSQXBqd1lLVzlRRkV2UCtCOWRxdHErenFsUVdUU0xFSmZobTNLSVdXUUlEUWEwdS9CRUZOYnhMRVVjR3pwdGNQZnRqaktUSjNzZCtwb1pTTlhpUUtKODNxNXpYaDM2QUxYQjlFN3IyTkZTNHlFdHJ6Q1ZqejNqSXhtT0E0TFRGUnNTV2V0aW13TXNrL1VxeFBUaUR5ZUJNQ1hPdCBLeWxlIEJhY3p5bnNraSAmbHQ7a3lsZS5iYWN6eW5za2lAd2VsbHNwcmluZ3dvcmxkd2lkZS5jb20mZ3Q7PC9zYW1sOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDpBdHRyaWJ1dGU+PHNhbWw6QXR0cmlidXRlIE5hbWU9ImxvZ2luU2hlbGwiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj4vYmluL3pzaDwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJzaGFkb3dMYXN0Q2hhbmdlIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+MTM2MzExOTAyODwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJ1cm46b2lkOjIuNS40LjQiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5CYWN6eW5za2k8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0idXJuOm9pZDoyLjUuNC4wIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+dG9wPC9zYW1sOkF0dHJpYnV0ZVZhbHVlPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpzdHJpbmciPnBvc2l4QWNjb3VudDwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5leHRlbnNpYmxlT2JqZWN0PC9zYW1sOkF0dHJpYnV0ZVZhbHVlPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpzdHJpbmciPmFjY291bnQ8L3NhbWw6QXR0cmlidXRlVmFsdWU+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+bGRhcFB1YmxpY0tleTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJ1cm46b2lkOjAuOS4yMzQyLjE5MjAwMzAwLjEwMC4xLjMiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5reWxlLmJhY3p5bnNraUB3ZWxsc3ByaW5nd29ybGR3aWRlLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJ1cm46b2lkOjIuNS40LjQyIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+S3lsZTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJ1cm46b2lkOjAuOS4yMzQyLjE5MjAwMzAwLjEwMC4xLjEiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5reWxlLmJhY3p5bnNraTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJ1cm46b2lkOjIuNS40LjMiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5LeWxlIEJhY3p5bnNraTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJ1cm46b2lkOjAuOS4yMzQyLjE5MjAwMzAwLjEwMC4xLjUiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5JY2VkIFRlYTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJ1cm46b2lkOjIuNS40LjM1IiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+e1NTSEF9RVB2V3V1bkMxU1p0Nk5OdHMveTdpcFRJcVVMVjZJVWU8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0idXJuOm9pZDowLjkuMjM0Mi4xOTIwMDMwMC4xMDAuMS45IiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+Kjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJ1cm46b2lkOjIuMTYuODQwLjEuMTEzNzMwLjMuMS4zOSIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpzdHJpbmciPmVuPC9zYW1sOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDpBdHRyaWJ1dGU+PC9zYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD48L3NhbWw6QXNzZXJ0aW9uPjwvc2FtbHA6UmVzcG9uc2U+
@@ -11,7 +11,8 @@ class SettingsTest < Test::Unit::TestCase
11
11
  :assertion_consumer_service_url, :issuer, :sp_name_qualifier,
12
12
  :idp_sso_target_url, :idp_cert_fingerprint, :name_identifier_format,
13
13
  :idp_slo_target_url, :name_identifier_value, :sessionindex,
14
- :assertion_consumer_logout_service_url
14
+ :assertion_consumer_logout_service_url,
15
+ :passive, :protocol_binding
15
16
  ]
16
17
 
17
18
  accessors.each do |accessor|
@@ -31,6 +32,8 @@ class SettingsTest < Test::Unit::TestCase
31
32
  :idp_slo_target_url => "http://sso.muda.no/slo",
32
33
  :idp_cert_fingerprint => "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
33
34
  :name_identifier_format => "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
35
+ :passive => true,
36
+ :protocol_binding => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
34
37
  }
35
38
  @settings = Onelogin::Saml::Settings.new(config)
36
39
 
@@ -1,8 +1,8 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
3
  require 'shoulda'
4
- require 'mocha'
5
4
  require 'ruby-debug'
5
+ require 'mocha/setup'
6
6
  require 'timecop'
7
7
 
8
8
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
@@ -41,6 +41,10 @@ class Test::Unit::TestCase
41
41
  @response_document5 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response5.xml.base64'))
42
42
  end
43
43
 
44
+ def r1_response_document_6
45
+ @response_document6 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'r1_response6.xml.base64'))
46
+ end
47
+
44
48
  def ampersands_response
45
49
  @ampersands_resposne ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_with_ampersands.xml.base64'))
46
50
  end
@@ -64,4 +68,8 @@ class Test::Unit::TestCase
64
68
  @signature1 ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'certificate1'))
65
69
  end
66
70
 
71
+ def r1_signature_2
72
+ @signature2 ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'r1_certificate2_base64'))
73
+ end
74
+
67
75
  end
@@ -11,31 +11,31 @@ class XmlSecurityTest < Test::Unit::TestCase
11
11
  end
12
12
 
13
13
  should "should run validate without throwing NS related exceptions" do
14
- assert !@document.validate_doc(@base64cert, true)
14
+ assert !@document.validate_signature(@base64cert, true)
15
15
  end
16
16
 
17
17
  should "should run validate with throwing NS related exceptions" do
18
18
  assert_raise(Onelogin::Saml::ValidationError) do
19
- @document.validate_doc(@base64cert, false)
19
+ @document.validate_signature(@base64cert, false)
20
20
  end
21
21
  end
22
-
22
+
23
23
  should "not raise an error when softly validating the document multiple times" do
24
24
  assert_nothing_raised do
25
- 2.times { @document.validate_doc(@base64cert, true) }
25
+ 2.times { @document.validate_signature(@base64cert, true) }
26
26
  end
27
27
  end
28
28
 
29
29
  should "should raise Fingerprint mismatch" do
30
30
  exception = assert_raise(Onelogin::Saml::ValidationError) do
31
- @document.validate("no:fi:ng:er:pr:in:t", false)
31
+ @document.validate_document("no:fi:ng:er:pr:in:t", false)
32
32
  end
33
33
  assert_equal("Fingerprint mismatch", exception.message)
34
34
  end
35
35
 
36
36
  should "should raise Digest mismatch" do
37
37
  exception = assert_raise(Onelogin::Saml::ValidationError) do
38
- @document.validate_doc(@base64cert, false)
38
+ @document.validate_signature(@base64cert, false)
39
39
  end
40
40
  assert_equal("Digest mismatch", exception.message)
41
41
  end
@@ -47,50 +47,60 @@ class XmlSecurityTest < Test::Unit::TestCase
47
47
  document = XMLSecurity::SignedDocument.new(response)
48
48
  base64cert = document.elements["//ds:X509Certificate"].text
49
49
  exception = assert_raise(Onelogin::Saml::ValidationError) do
50
- document.validate_doc(base64cert, false)
50
+ document.validate_signature(base64cert, false)
51
51
  end
52
52
  assert_equal("Key validation error", exception.message)
53
53
  end
54
+
55
+ should "raise validation error when the X509Certificate is missing" do
56
+ response = Base64.decode64(response_document)
57
+ response.sub!(/<ds:X509Certificate>.*<\/ds:X509Certificate>/, "")
58
+ document = XMLSecurity::SignedDocument.new(response)
59
+ exception = assert_raise(Onelogin::Saml::ValidationError) do
60
+ document.validate_document("a fingerprint", false) # The fingerprint isn't relevant to this test
61
+ end
62
+ assert_equal("Certificate element missing in response (ds:X509Certificate)", exception.message)
63
+ end
54
64
  end
55
65
 
56
66
  context "Algorithms" do
57
67
  should "validate using SHA1" do
58
68
  @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha1, false))
59
- assert @document.validate("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
69
+ assert @document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
60
70
  end
61
71
 
62
72
  should "validate using SHA256" do
63
73
  @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha256, false))
64
- assert @document.validate("28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA")
74
+ assert @document.validate_document("28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA")
65
75
  end
66
76
 
67
77
  should "validate using SHA384" do
68
78
  @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha384, false))
69
- assert @document.validate("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
79
+ assert @document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
70
80
  end
71
81
 
72
82
  should "validate using SHA512" do
73
83
  @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha512, false))
74
- assert @document.validate("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
84
+ assert @document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
75
85
  end
76
86
  end
77
-
87
+
78
88
  context "XmlSecurity::SignedDocument" do
79
-
89
+
80
90
  context "#extract_inclusive_namespaces" do
81
91
  should "support explicit namespace resolution for exclusive canonicalization" do
82
92
  response = fixture(:open_saml_response, false)
83
93
  document = XMLSecurity::SignedDocument.new(response)
84
94
  inclusive_namespaces = document.send(:extract_inclusive_namespaces)
85
-
95
+
86
96
  assert_equal %w[ xs ], inclusive_namespaces
87
97
  end
88
-
98
+
89
99
  should "support implicit namespace resolution for exclusive canonicalization" do
90
100
  response = fixture(:no_signature_ns, false)
91
101
  document = XMLSecurity::SignedDocument.new(response)
92
102
  inclusive_namespaces = document.send(:extract_inclusive_namespaces)
93
-
103
+
94
104
  assert_equal %w[ #default saml ds xs xsi ], inclusive_namespaces
95
105
  end
96
106
 
@@ -110,10 +120,10 @@ class XmlSecurityTest < Test::Unit::TestCase
110
120
  should "return an empty list when inclusive namespace element is missing" do
111
121
  response = fixture(:no_signature_ns, false)
112
122
  response.slice! %r{<InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="#default saml ds xs xsi"/>}
113
-
123
+
114
124
  document = XMLSecurity::SignedDocument.new(response)
115
125
  inclusive_namespaces = document.send(:extract_inclusive_namespaces)
116
-
126
+
117
127
  assert inclusive_namespaces.empty?
118
128
  end
119
129
  end
@@ -146,5 +156,5 @@ class XmlSecurityTest < Test::Unit::TestCase
146
156
  end
147
157
 
148
158
  end
149
-
159
+
150
160
  end
metadata CHANGED
@@ -1,72 +1,79 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml
3
- version: !ruby/object:Gem::Version
4
- version: 0.7.2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 5
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 7
9
+ - 3
10
+ version: 0.7.3
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - OneLogin LLC
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2013-02-22 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2014-02-20 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: canonix
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - '='
20
- - !ruby/object:Gem::Version
21
- version: 0.1.1
22
- type: :runtime
23
22
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
25
24
  none: false
26
- requirements:
27
- - - '='
28
- - !ruby/object:Gem::Version
25
+ requirements:
26
+ - - "="
27
+ - !ruby/object:Gem::Version
28
+ hash: 25
29
+ segments:
30
+ - 0
31
+ - 1
32
+ - 1
29
33
  version: 0.1.1
30
- - !ruby/object:Gem::Dependency
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
31
37
  name: uuid
32
- requirement: !ruby/object:Gem::Requirement
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
33
40
  none: false
34
- requirements:
41
+ requirements:
35
42
  - - ~>
36
- - !ruby/object:Gem::Version
37
- version: '2.3'
43
+ - !ruby/object:Gem::Version
44
+ hash: 5
45
+ segments:
46
+ - 2
47
+ - 3
48
+ version: "2.3"
38
49
  type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: nokogiri
39
53
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
54
+ requirement: &id003 !ruby/object:Gem::Requirement
41
55
  none: false
42
- requirements:
56
+ requirements:
43
57
  - - ~>
44
- - !ruby/object:Gem::Version
45
- version: '2.3'
46
- - !ruby/object:Gem::Dependency
47
- name: nokogiri
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: '0'
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 1
62
+ - 5
63
+ - 0
64
+ version: 1.5.0
54
65
  type: :runtime
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
66
+ version_requirements: *id003
62
67
  description: SAML toolkit for Ruby on Rails
63
68
  email: support@onelogin.com
64
69
  executables: []
70
+
65
71
  extensions: []
66
- extra_rdoc_files:
72
+
73
+ extra_rdoc_files:
67
74
  - LICENSE
68
75
  - README.md
69
- files:
76
+ files:
70
77
  - .document
71
78
  - .gitignore
72
79
  - .travis.yml
@@ -91,6 +98,7 @@ files:
91
98
  - lib/xml_security.rb
92
99
  - ruby-saml.gemspec
93
100
  - test/certificates/certificate1
101
+ - test/certificates/r1_certificate2_base64
94
102
  - test/logoutrequest_test.rb
95
103
  - test/logoutresponse_test.rb
96
104
  - test/request_test.rb
@@ -102,6 +110,7 @@ files:
102
110
  - test/responses/logoutresponse_fixtures.rb
103
111
  - test/responses/no_signature_ns.xml
104
112
  - test/responses/open_saml_response.xml
113
+ - test/responses/r1_response6.xml.base64
105
114
  - test/responses/response1.xml.base64
106
115
  - test/responses/response2.xml.base64
107
116
  - test/responses/response3.xml.base64
@@ -117,31 +126,40 @@ files:
117
126
  - test/xml_security_test.rb
118
127
  homepage: http://github.com/onelogin/ruby-saml
119
128
  licenses: []
129
+
120
130
  post_install_message:
121
- rdoc_options:
131
+ rdoc_options:
122
132
  - --charset=UTF-8
123
- require_paths:
133
+ require_paths:
124
134
  - lib
125
- required_ruby_version: !ruby/object:Gem::Requirement
135
+ required_ruby_version: !ruby/object:Gem::Requirement
126
136
  none: false
127
- requirements:
128
- - - ! '>='
129
- - !ruby/object:Gem::Version
130
- version: '0'
131
- required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ hash: 3
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
145
  none: false
133
- requirements:
134
- - - ! '>='
135
- - !ruby/object:Gem::Version
136
- version: '0'
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ hash: 3
150
+ segments:
151
+ - 0
152
+ version: "0"
137
153
  requirements: []
154
+
138
155
  rubyforge_project: http://www.rubygems.org/gems/ruby-saml
139
- rubygems_version: 1.8.23
156
+ rubygems_version: 1.8.25
140
157
  signing_key:
141
158
  specification_version: 3
142
159
  summary: SAML Ruby Tookit
143
- test_files:
160
+ test_files:
144
161
  - test/certificates/certificate1
162
+ - test/certificates/r1_certificate2_base64
145
163
  - test/logoutrequest_test.rb
146
164
  - test/logoutresponse_test.rb
147
165
  - test/request_test.rb
@@ -153,6 +171,7 @@ test_files:
153
171
  - test/responses/logoutresponse_fixtures.rb
154
172
  - test/responses/no_signature_ns.xml
155
173
  - test/responses/open_saml_response.xml
174
+ - test/responses/r1_response6.xml.base64
156
175
  - test/responses/response1.xml.base64
157
176
  - test/responses/response2.xml.base64
158
177
  - test/responses/response3.xml.base64
@@ -166,4 +185,3 @@ test_files:
166
185
  - test/settings_test.rb
167
186
  - test/test_helper.rb
168
187
  - test/xml_security_test.rb
169
- has_rdoc: