ruby-saml 0.8.5 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ruby-saml might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA512:
3
- metadata.gz: 8489326fd3207aa709c005557141665444ef5653c4850520908e7bbc16cb8cb6529fe6bf7d85ee7cb7f896a441ac078fa8eca87341c1737bbb8cc2c6a1712e54
4
- data.tar.gz: dc7006007ed9e9bfa190401c4e003992ff66786854dfac4725b956714281eba2503d83814653674f171a02885c136adc078d5c13e3d6277f9677989591c6d375
5
- SHA256:
6
- metadata.gz: 024d00094972f6386863705f834f4ecb2c4e42d5b462181573151493211cfd52
7
- data.tar.gz: 7346f35e9750a26de6b4d1079817ef148945c4949bdaa05ba0249e72ecac0a64
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 57e7a2eb4f514972244fc12215e6586386fb5fe3
4
+ data.tar.gz: cf05522f6c29de7ae71c30407a93ee2cfe5926b9
5
+ SHA512:
6
+ metadata.gz: 039cc1a41f64dd95707f441afc2015bc44948944fa0356ead52280d5420ebc314d9b004f3e048694356aa40b36546c0a3a98e2f8e4c98f79079b199629f4872f
7
+ data.tar.gz: 57a46834046c71fce8a1845487e6dfb53fb6b9dadac4d411462e2e2731c8457b162be13563fbad92f3f15e7639916c59e8a266842d018191c40cbfb5f77038c6
@@ -0,0 +1,128 @@
1
+ module OneLogin
2
+ module RubySaml
3
+
4
+ # SAML2 Attributes. Parse the Attributes from the AttributeStatement of the SAML Response.
5
+ #
6
+ class Attributes
7
+ include Enumerable
8
+
9
+ attr_reader :attributes
10
+
11
+ # By default Attributes#[] is backwards compatible and
12
+ # returns only the first value for the attribute
13
+ # Setting this to `false` returns all values for an attribute
14
+ @@single_value_compatibility = true
15
+
16
+ # @return [Boolean] Get current status of backwards compatibility mode.
17
+ #
18
+ def self.single_value_compatibility
19
+ @@single_value_compatibility
20
+ end
21
+
22
+ # Sets the backwards compatibility mode on/off.
23
+ # @param value [Boolean]
24
+ #
25
+ def self.single_value_compatibility=(value)
26
+ @@single_value_compatibility = value
27
+ end
28
+
29
+ # @param attrs [Hash] The +attrs+ must be a Hash with attribute names as keys and **arrays** as values:
30
+ # Attributes.new({
31
+ # 'name' => ['value1', 'value2'],
32
+ # 'mail' => ['value1'],
33
+ # })
34
+ #
35
+ def initialize(attrs = {})
36
+ @attributes = attrs
37
+ end
38
+
39
+
40
+ # Iterate over all attributes
41
+ #
42
+ def each
43
+ attributes.each{|name, values| yield name, values}
44
+ end
45
+
46
+
47
+ # Test attribute presence by name
48
+ # @param name [String] The attribute name to be checked
49
+ #
50
+ def include?(name)
51
+ attributes.has_key?(canonize_name(name))
52
+ end
53
+
54
+ # Return first value for an attribute
55
+ # @param name [String] The attribute name
56
+ # @return [String] The value (First occurrence)
57
+ #
58
+ def single(name)
59
+ attributes[canonize_name(name)].first if include?(name)
60
+ end
61
+
62
+ # Return all values for an attribute
63
+ # @param name [String] The attribute name
64
+ # @return [Array] Values of the attribute
65
+ #
66
+ def multi(name)
67
+ attributes[canonize_name(name)]
68
+ end
69
+
70
+ # Retrieve attribute value(s)
71
+ # @param name [String] The attribute name
72
+ # @return [String|Array] Depending on the single value compatibility status this returns:
73
+ # - First value if single_value_compatibility = true
74
+ # response.attributes['mail'] # => 'user@example.com'
75
+ # - All values if single_value_compatibility = false
76
+ # response.attributes['mail'] # => ['user@example.com','user@example.net']
77
+ #
78
+ def [](name)
79
+ self.class.single_value_compatibility ? single(canonize_name(name)) : multi(canonize_name(name))
80
+ end
81
+
82
+ # @return [Array] Return all attributes as an array
83
+ #
84
+ def all
85
+ attributes
86
+ end
87
+
88
+ # @param name [String] The attribute name
89
+ # @param values [Array] The values
90
+ #
91
+ def set(name, values)
92
+ attributes[canonize_name(name)] = values
93
+ end
94
+ alias_method :[]=, :set
95
+
96
+ # @param name [String] The attribute name
97
+ # @param values [Array] The values
98
+ #
99
+ def add(name, values = [])
100
+ attributes[canonize_name(name)] ||= []
101
+ attributes[canonize_name(name)] += Array(values)
102
+ end
103
+
104
+ # Make comparable to another Attributes collection based on attributes
105
+ # @param other [Attributes] An Attributes object to compare with
106
+ # @return [Boolean] True if are contains the same attributes and values
107
+ #
108
+ def ==(other)
109
+ if other.is_a?(Attributes)
110
+ all == other.all
111
+ else
112
+ super
113
+ end
114
+ end
115
+
116
+ protected
117
+
118
+ # stringifies all names so both 'email' and :email return the same result
119
+ # @param name [String] The attribute name
120
+ # @return [String] stringified name
121
+ #
122
+ def canonize_name(name)
123
+ name.to_s
124
+ end
125
+
126
+ end
127
+ end
128
+ end
@@ -1,6 +1,7 @@
1
1
  require "xml_security"
2
2
  require "time"
3
3
  require "nokogiri"
4
+ require 'onelogin/ruby-saml/attributes'
4
5
 
5
6
  # Only supports SAML 2.0
6
7
  module OneLogin
@@ -48,26 +49,48 @@ module OneLogin
48
49
  end
49
50
  end
50
51
 
51
- # A hash of alle the attributes with the response. Assuming there is only one value for each key
52
+ # Gets the Attributes from the AttributeStatement element.
53
+ #
54
+ # All attributes can be iterated over +attributes.each+ or returned as array by +attributes.all+
55
+ # For backwards compatibility ruby-saml returns by default only the first value for a given attribute with
56
+ # attributes['name']
57
+ # To get all of the attributes, use:
58
+ # attributes.multi('name')
59
+ # Or turn off the compatibility:
60
+ # OneLogin::RubySaml::Attributes.single_value_compatibility = false
61
+ # Now this will return an array:
62
+ # attributes['name']
63
+ #
64
+ # @return [Attributes] OneLogin::RubySaml::Attributes enumerable collection.
65
+ #
52
66
  def attributes
53
67
  @attr_statements ||= begin
54
- result = {}
55
-
56
- stmt_element = xpath_first_from_signed_assertion('/a:AttributeStatement')
57
- return {} if stmt_element.nil?
58
-
59
- stmt_element.elements.each do |attr_element|
60
- name = attr_element.attributes["Name"]
61
- value = Utils.element_text(attr_element.elements.first)
62
-
63
- result[name] = value
64
- end
65
-
66
- result.keys.each do |key|
67
- result[key.intern] = result[key]
68
+ attributes = Attributes.new
69
+
70
+ stmt_elements = xpath_from_signed_assertion('/a:AttributeStatement')
71
+ stmt_elements.each do |stmt_element|
72
+ stmt_element.elements.each do |attr_element|
73
+ name = attr_element.attributes["Name"]
74
+ values = attr_element.elements.collect{|e|
75
+ if (e.elements.nil? || e.elements.size == 0)
76
+ # SAMLCore requires that nil AttributeValues MUST contain xsi:nil XML attribute set to "true" or "1"
77
+ # otherwise the value is to be regarded as empty.
78
+ ["true", "1"].include?(e.attributes['xsi:nil']) ? nil : Utils.element_text(e)
79
+ # explicitly support saml2:NameID with saml2:NameQualifier if supplied in attributes
80
+ # this is useful for allowing eduPersonTargetedId to be passed as an opaque identifier to use to
81
+ # identify the subject in an SP rather than email or other less opaque attributes
82
+ # NameQualifier, if present is prefixed with a "/" to the value
83
+ else
84
+ REXML::XPath.match(e,'a:NameID', { "a" => ASSERTION }).collect{|n|
85
+ (n.attributes['NameQualifier'] ? n.attributes['NameQualifier'] +"/" : '') + Utils.element_text(n)
86
+ }
87
+ end
88
+ }
89
+
90
+ attributes.add(name, values.flatten)
91
+ end
68
92
  end
69
-
70
- result
93
+ attributes
71
94
  end
72
95
  end
73
96
 
@@ -166,6 +189,26 @@ module OneLogin
166
189
  node
167
190
  end
168
191
 
192
+ # Extracts all the appearances that matchs the subelt (pattern)
193
+ # Search on any Assertion that is signed, or has a Response parent signed
194
+ # @param subelt [String] The XPath pattern
195
+ # @return [Array of REXML::Element] Return all matches
196
+ #
197
+ def xpath_from_signed_assertion(subelt=nil)
198
+ node = REXML::XPath.match(
199
+ document,
200
+ "/p:Response/a:Assertion[@ID=$id]#{subelt}",
201
+ { "p" => PROTOCOL, "a" => ASSERTION },
202
+ { 'id' => document.signed_element_id }
203
+ )
204
+ node.concat( REXML::XPath.match(
205
+ document,
206
+ "/p:Response[@ID=$id]/a:Assertion#{subelt}",
207
+ { "p" => PROTOCOL, "a" => ASSERTION },
208
+ { 'id' => document.signed_element_id }
209
+ ))
210
+ end
211
+
169
212
  def get_fingerprint
170
213
  if settings.idp_cert
171
214
  cert = OpenSSL::X509::Certificate.new(settings.idp_cert)
@@ -1,5 +1,5 @@
1
1
  module OneLogin
2
2
  module RubySaml
3
- VERSION = '0.8.5'
3
+ VERSION = '0.8.6'
4
4
  end
5
5
  end
@@ -8,3 +8,4 @@ require 'onelogin/ruby-saml/utils'
8
8
  require 'onelogin/ruby-saml/validation_error'
9
9
  require 'onelogin/ruby-saml/metadata'
10
10
  require 'onelogin/ruby-saml/version'
11
+ require 'onelogin/ruby-saml/attributes'
@@ -229,7 +229,12 @@ class RubySamlTest < Test::Unit::TestCase
229
229
 
230
230
  should "not raise on responses without attributes" do
231
231
  response = OneLogin::RubySaml::Response.new(response_document_4)
232
- assert_equal Hash.new, response.attributes
232
+ assert_equal OneLogin::RubySaml::Attributes.new, response.attributes
233
+ end
234
+
235
+ should "extract attributes from all AttributeStatement tags" do
236
+ assert_equal "smith", response_with_multiple_attribute_statements.attributes[:surname]
237
+ assert_equal "bob", response_with_multiple_attribute_statements.attributes[:firstname]
233
238
  end
234
239
  end
235
240
 
@@ -270,5 +275,97 @@ class RubySamlTest < Test::Unit::TestCase
270
275
  assert_equal($evalled, nil)
271
276
  end
272
277
  end
278
+
279
+ context "#multiple values" do
280
+ should "extract single value as string" do
281
+ assert_equal "demo", response_multiple_attr_values.attributes[:uid]
282
+ end
283
+
284
+ should "extract single value as string in compatibility mode off" do
285
+ OneLogin::RubySaml::Attributes.single_value_compatibility = false
286
+ assert_equal ["demo"], response_multiple_attr_values.attributes[:uid]
287
+ # classes are not reloaded between tests so restore default
288
+ OneLogin::RubySaml::Attributes.single_value_compatibility = true
289
+ end
290
+
291
+ should "extract first of multiple values as string for b/w compatibility" do
292
+ assert_equal 'value1', response_multiple_attr_values.attributes[:another_value]
293
+ end
294
+
295
+ should "extract first of multiple values as string for b/w compatibility in compatibility mode off" do
296
+ OneLogin::RubySaml::Attributes.single_value_compatibility = false
297
+ assert_equal ['value1', 'value2'], response_multiple_attr_values.attributes[:another_value]
298
+ OneLogin::RubySaml::Attributes.single_value_compatibility = true
299
+ end
300
+
301
+ should "return array with all attributes when asked in XML order" do
302
+ assert_equal ['value1', 'value2'], response_multiple_attr_values.attributes.multi(:another_value)
303
+ end
304
+
305
+ should "return array with all attributes when asked in XML order in compatibility mode off" do
306
+ OneLogin::RubySaml::Attributes.single_value_compatibility = false
307
+ assert_equal ['value1', 'value2'], response_multiple_attr_values.attributes.multi(:another_value)
308
+ OneLogin::RubySaml::Attributes.single_value_compatibility = true
309
+ end
310
+
311
+ should "return first of multiple values when multiple Attribute tags in XML" do
312
+ assert_equal 'role1', response_multiple_attr_values.attributes[:role]
313
+ end
314
+
315
+ should "return first of multiple values when multiple Attribute tags in XML in compatibility mode off" do
316
+ OneLogin::RubySaml::Attributes.single_value_compatibility = false
317
+ assert_equal ['role1', 'role2', 'role3'], response_multiple_attr_values.attributes[:role]
318
+ OneLogin::RubySaml::Attributes.single_value_compatibility = true
319
+ end
320
+
321
+ should "return all of multiple values in reverse order when multiple Attribute tags in XML" do
322
+ assert_equal ['role1', 'role2', 'role3'], response_multiple_attr_values.attributes.multi(:role)
323
+ end
324
+
325
+ should "return all of multiple values in reverse order when multiple Attribute tags in XML in compatibility mode off" do
326
+ OneLogin::RubySaml::Attributes.single_value_compatibility = false
327
+ assert_equal ['role1', 'role2', 'role3'], response_multiple_attr_values.attributes.multi(:role)
328
+ OneLogin::RubySaml::Attributes.single_value_compatibility = true
329
+ end
330
+
331
+ should "return all of multiple values when multiple Attribute tags in multiple AttributeStatement tags" do
332
+ OneLogin::RubySaml::Attributes.single_value_compatibility = false
333
+ assert_equal ['role1', 'role2', 'role3'], response_with_multiple_attribute_statements.attributes.multi(:role)
334
+ OneLogin::RubySaml::Attributes.single_value_compatibility = true
335
+ end
336
+
337
+ should "return nil value correctly" do
338
+ assert_nil response_multiple_attr_values.attributes[:attribute_with_nil_value]
339
+ end
340
+
341
+ should "return nil value correctly when not in compatibility mode off" do
342
+ OneLogin::RubySaml::Attributes.single_value_compatibility = false
343
+ assert_equal [nil], response_multiple_attr_values.attributes[:attribute_with_nil_value]
344
+ OneLogin::RubySaml::Attributes.single_value_compatibility = true
345
+ end
346
+
347
+ should "return multiple values including nil and empty string" do
348
+ response = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
349
+ assert_equal ["", "valuePresent", nil, nil], response.attributes.multi(:attribute_with_nils_and_empty_strings)
350
+ end
351
+
352
+ should "return multiple values from [] when not in compatibility mode off" do
353
+ OneLogin::RubySaml::Attributes.single_value_compatibility = false
354
+ assert_equal ["", "valuePresent", nil, nil], response_multiple_attr_values.attributes[:attribute_with_nils_and_empty_strings]
355
+ OneLogin::RubySaml::Attributes.single_value_compatibility = true
356
+ end
357
+
358
+ should "check what happens when trying retrieve attribute that does not exists" do
359
+ assert_equal nil, response_multiple_attr_values.attributes[:attribute_not_exists]
360
+ assert_equal nil, response_multiple_attr_values.attributes.single(:attribute_not_exists)
361
+ assert_equal nil, response_multiple_attr_values.attributes.multi(:attribute_not_exists)
362
+
363
+ OneLogin::RubySaml::Attributes.single_value_compatibility = false
364
+ assert_equal nil, response_multiple_attr_values.attributes[:attribute_not_exists]
365
+ assert_equal nil, response_multiple_attr_values.attributes.single(:attribute_not_exists)
366
+ assert_equal nil, response_multiple_attr_values.attributes.multi(:attribute_not_exists)
367
+ OneLogin::RubySaml::Attributes.single_value_compatibility = true
368
+ end
369
+ end
273
370
  end
274
371
  end
@@ -0,0 +1,72 @@
1
+ <samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="GOSAMLR12901174571794" Version="2.0" IssueInstant="2010-11-18T21:57:37Z" Destination="{recipient}">
2
+ <samlp:Status>
3
+ <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>
4
+ <saml:Assertion xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="2.0" ID="pfxa46574df-b3b0-a06a-23c8-636413198772" IssueInstant="2010-11-18T21:57:37Z">
5
+ <saml:Issuer>https://app.onelogin.com/saml/metadata/13590</saml:Issuer>
6
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
7
+ <ds:SignedInfo>
8
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
9
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
10
+ <ds:Reference URI="#pfxa46574df-b3b0-a06a-23c8-636413198772">
11
+ <ds:Transforms>
12
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
13
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
14
+ </ds:Transforms>
15
+ <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
16
+ <ds:DigestValue>pJQ7MS/ek4KRRWGmv/H43ReHYMs=</ds:DigestValue>
17
+ </ds:Reference>
18
+ </ds:SignedInfo>
19
+ <ds:SignatureValue>yiveKcPdDpuDNj6shrQ3ABwr/cA3CryD2phG/xLZszKWxU5/mlaKt8ewbZOdKKvtOs2pHBy5Dua3k94AF+zxGyel5gOowmoyXJr+AOr+kPO0vli1V8o3hPPUZwRgSX6Q9pS1CqQghKiEasRyylqqJUaPYzmOzOE8/XlMkwiWmO0=</ds:SignatureValue>
20
+ <ds:KeyInfo>
21
+ <ds:X509Data>
22
+ <ds:X509Certificate>MIIBrTCCAaGgAwIBAgIBATADBgEAMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9uZUxvZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMB4XDTEwMDMwOTA5NTg0NVoXDTE1MDMwOTA5NTg0NVowZzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAcMDFNhbnRhIE1vbmljYTERMA8GA1UECgwIT25lTG9naW4xGTAXBgNVBAMMEGFwcC5vbmVsb2dpbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOjSu1fjPy8d5w4QyL1+zd4hIw1Mkkff4WY/TLG8OZkU5YTSWmmHPD5kvYH5uoXS/6qQ81qXpR2wV8CTowZJULg09ddRdRn8Qsqj1FyOC5slE3y2bZ2oFua72of/49fpujnFT6KnQ61CBMqlDoTQqOT62vGJ8nP6MZWvA6sxqud5AgMBAAEwAwYBAAMBAA==</ds:X509Certificate>
23
+ </ds:X509Data>
24
+ </ds:KeyInfo>
25
+ </ds:Signature>
26
+ <saml:Subject>
27
+ <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">support@onelogin.com</saml:NameID>
28
+ <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
29
+ <saml:SubjectConfirmationData NotOnOrAfter="2010-11-18T22:02:37Z" Recipient="{recipient}"/></saml:SubjectConfirmation>
30
+ </saml:Subject>
31
+ <saml:Conditions NotBefore="2010-11-18T21:52:37Z" NotOnOrAfter="2010-11-18T22:02:37Z">
32
+ <saml:AudienceRestriction>
33
+ <saml:Audience>{audience}</saml:Audience>
34
+ </saml:AudienceRestriction>
35
+ </saml:Conditions>
36
+ <saml:AuthnStatement AuthnInstant="2010-11-18T21:57:37Z" SessionNotOnOrAfter="2010-11-19T21:57:37Z" SessionIndex="_531c32d283bdff7e04e487bcdbc4dd8d">
37
+ <saml:AuthnContext>
38
+ <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
39
+ </saml:AuthnContext>
40
+ </saml:AuthnStatement>
41
+ <saml:AttributeStatement>
42
+ <saml:Attribute Name="surname">
43
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">smith</saml:AttributeValue>
44
+ </saml:Attribute>
45
+ <saml:Attribute Name="another_value">
46
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">value1</saml:AttributeValue>
47
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">value2</saml:AttributeValue>
48
+ </saml:Attribute>
49
+ <saml:Attribute Name="role">
50
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">role1</saml:AttributeValue>
51
+ </saml:Attribute>
52
+ </saml:AttributeStatement>
53
+ <saml:AttributeStatement>
54
+ <saml:Attribute Name="firstname">
55
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">bob</saml:AttributeValue>
56
+ </saml:Attribute>
57
+ <saml:Attribute Name="role">
58
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">role2</saml:AttributeValue>
59
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">role3</saml:AttributeValue>
60
+ </saml:Attribute>
61
+ <saml:Attribute Name="attribute_with_nil_value">
62
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
63
+ </saml:Attribute>
64
+ <saml:Attribute Name="attribute_with_nils_and_empty_strings">
65
+ <saml:AttributeValue/>
66
+ <saml:AttributeValue>valuePresent</saml:AttributeValue>
67
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
68
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="1"/>
69
+ </saml:Attribute>
70
+ </saml:AttributeStatement>
71
+ </saml:Assertion>
72
+ </samlp:Response>
@@ -0,0 +1,67 @@
1
+ <samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="GOSAMLR12901174571794" Version="2.0" IssueInstant="2010-11-18T21:57:37Z" Destination="{recipient}">
2
+ <samlp:Status>
3
+ <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>
4
+ <saml:Assertion xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="2.0" ID="pfxa46574df-b3b0-a06a-23c8-636413198772" IssueInstant="2010-11-18T21:57:37Z">
5
+ <saml:Issuer>https://app.onelogin.com/saml/metadata/13590</saml:Issuer>
6
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
7
+ <ds:SignedInfo>
8
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
9
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
10
+ <ds:Reference URI="#pfxa46574df-b3b0-a06a-23c8-636413198772">
11
+ <ds:Transforms>
12
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
13
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
14
+ </ds:Transforms>
15
+ <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
16
+ <ds:DigestValue>pJQ7MS/ek4KRRWGmv/H43ReHYMs=</ds:DigestValue>
17
+ </ds:Reference>
18
+ </ds:SignedInfo>
19
+ <ds:SignatureValue>yiveKcPdDpuDNj6shrQ3ABwr/cA3CryD2phG/xLZszKWxU5/mlaKt8ewbZOdKKvtOs2pHBy5Dua3k94AF+zxGyel5gOowmoyXJr+AOr+kPO0vli1V8o3hPPUZwRgSX6Q9pS1CqQghKiEasRyylqqJUaPYzmOzOE8/XlMkwiWmO0=</ds:SignatureValue>
20
+ <ds:KeyInfo>
21
+ <ds:X509Data>
22
+ <ds:X509Certificate>MIIBrTCCAaGgAwIBAgIBATADBgEAMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9uZUxvZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMB4XDTEwMDMwOTA5NTg0NVoXDTE1MDMwOTA5NTg0NVowZzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAcMDFNhbnRhIE1vbmljYTERMA8GA1UECgwIT25lTG9naW4xGTAXBgNVBAMMEGFwcC5vbmVsb2dpbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOjSu1fjPy8d5w4QyL1+zd4hIw1Mkkff4WY/TLG8OZkU5YTSWmmHPD5kvYH5uoXS/6qQ81qXpR2wV8CTowZJULg09ddRdRn8Qsqj1FyOC5slE3y2bZ2oFua72of/49fpujnFT6KnQ61CBMqlDoTQqOT62vGJ8nP6MZWvA6sxqud5AgMBAAEwAwYBAAMBAA==</ds:X509Certificate>
23
+ </ds:X509Data>
24
+ </ds:KeyInfo>
25
+ </ds:Signature>
26
+ <saml:Subject>
27
+ <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">support@onelogin.com</saml:NameID>
28
+ <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
29
+ <saml:SubjectConfirmationData NotOnOrAfter="2010-11-18T22:02:37Z" Recipient="{recipient}"/></saml:SubjectConfirmation>
30
+ </saml:Subject>
31
+ <saml:Conditions NotBefore="2010-11-18T21:52:37Z" NotOnOrAfter="2010-11-18T22:02:37Z">
32
+ <saml:AudienceRestriction>
33
+ <saml:Audience>{audience}</saml:Audience>
34
+ </saml:AudienceRestriction>
35
+ </saml:Conditions>
36
+ <saml:AuthnStatement AuthnInstant="2010-11-18T21:57:37Z" SessionNotOnOrAfter="2010-11-19T21:57:37Z" SessionIndex="_531c32d283bdff7e04e487bcdbc4dd8d">
37
+ <saml:AuthnContext>
38
+ <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
39
+ </saml:AuthnContext>
40
+ </saml:AuthnStatement>
41
+ <saml:AttributeStatement>
42
+ <saml:Attribute Name="uid">
43
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">demo</saml:AttributeValue>
44
+ </saml:Attribute>
45
+ <saml:Attribute Name="another_value">
46
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">value1</saml:AttributeValue>
47
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">value2</saml:AttributeValue>
48
+ </saml:Attribute>
49
+ <saml:Attribute Name="role">
50
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">role1</saml:AttributeValue>
51
+ </saml:Attribute>
52
+ <saml:Attribute Name="role">
53
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">role2</saml:AttributeValue>
54
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">role3</saml:AttributeValue>
55
+ </saml:Attribute>
56
+ <saml:Attribute Name="attribute_with_nil_value">
57
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
58
+ </saml:Attribute>
59
+ <saml:Attribute Name="attribute_with_nils_and_empty_strings">
60
+ <saml:AttributeValue/>
61
+ <saml:AttributeValue>valuePresent</saml:AttributeValue>
62
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
63
+ <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="1"/>
64
+ </saml:Attribute>
65
+ </saml:AttributeStatement>
66
+ </saml:Assertion>
67
+ </samlp:Response>
@@ -71,4 +71,12 @@ class Test::Unit::TestCase
71
71
  @signature2 ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'r1_certificate2_base64'))
72
72
  end
73
73
 
74
+ def response_with_multiple_attribute_statements
75
+ @response_with_multiple_attribute_statements = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_statements))
76
+ end
77
+
78
+ def response_multiple_attr_values
79
+ @response_multiple_attr_values = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
80
+ end
81
+
74
82
  end
metadata CHANGED
@@ -1,54 +1,60 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml
3
- version: !ruby/object:Gem::Version
4
- version: 0.8.5
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.6
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - OneLogin LLC
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2018-09-12 00:00:00 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
11
+ date: 2019-02-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
15
14
  name: uuid
16
- prerelease: false
17
- requirement: &id001 !ruby/object:Gem::Requirement
18
- requirements:
19
- - - ~>
20
- - !ruby/object:Gem::Version
21
- version: "2.3"
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
22
20
  type: :runtime
23
- version_requirements: *id001
24
- - !ruby/object:Gem::Dependency
25
- name: nokogiri
26
21
  prerelease: false
27
- requirement: &id002 !ruby/object:Gem::Requirement
28
- requirements:
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
29
31
  - - ">="
30
- - !ruby/object:Gem::Version
32
+ - !ruby/object:Gem::Version
31
33
  version: 1.5.0
32
34
  type: :runtime
33
- version_requirements: *id002
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.5.0
34
41
  description: SAML toolkit for Ruby on Rails
35
42
  email: support@onelogin.com
36
43
  executables: []
37
-
38
44
  extensions: []
39
-
40
- extra_rdoc_files:
45
+ extra_rdoc_files:
41
46
  - LICENSE
42
47
  - README.md
43
- files:
44
- - .document
45
- - .gitignore
46
- - .travis.yml
48
+ files:
49
+ - ".document"
50
+ - ".gitignore"
51
+ - ".travis.yml"
47
52
  - Gemfile
48
53
  - LICENSE
49
54
  - README.md
50
55
  - Rakefile
51
56
  - changelog.md
57
+ - lib/onelogin/ruby-saml/attributes.rb
52
58
  - lib/onelogin/ruby-saml/authrequest.rb
53
59
  - lib/onelogin/ruby-saml/logging.rb
54
60
  - lib/onelogin/ruby-saml/logoutrequest.rb
@@ -89,6 +95,8 @@ files:
89
95
  - test/responses/response_node_text_attack.xml.base64
90
96
  - test/responses/response_with_ampersands.xml
91
97
  - test/responses/response_with_ampersands.xml.base64
98
+ - test/responses/response_with_multiple_attribute_statements.xml
99
+ - test/responses/response_with_multiple_attribute_values.xml
92
100
  - test/responses/simple_saml_php.xml
93
101
  - test/responses/starfield_response.xml.base64
94
102
  - test/responses/wrapped_response_2.xml.base64
@@ -98,31 +106,29 @@ files:
98
106
  - test/xml_security_test.rb
99
107
  homepage: http://github.com/onelogin/ruby-saml
100
108
  licenses: []
101
-
102
109
  metadata: {}
103
-
104
110
  post_install_message:
105
- rdoc_options:
106
- - --charset=UTF-8
107
- require_paths:
111
+ rdoc_options:
112
+ - "--charset=UTF-8"
113
+ require_paths:
108
114
  - lib
109
- required_ruby_version: !ruby/object:Gem::Requirement
110
- requirements:
111
- - &id003
112
- - ">="
113
- - !ruby/object:Gem::Version
114
- version: "0"
115
- required_rubygems_version: !ruby/object:Gem::Requirement
116
- requirements:
117
- - *id003
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
118
125
  requirements: []
119
-
120
126
  rubyforge_project: http://www.rubygems.org/gems/ruby-saml
121
- rubygems_version: 2.7.7
127
+ rubygems_version: 2.5.2.1
122
128
  signing_key:
123
129
  specification_version: 4
124
130
  summary: SAML Ruby Tookit
125
- test_files:
131
+ test_files:
126
132
  - test/certificates/certificate1
127
133
  - test/certificates/r1_certificate2_base64
128
134
  - test/logoutrequest_test.rb
@@ -146,6 +152,8 @@ test_files:
146
152
  - test/responses/response_node_text_attack.xml.base64
147
153
  - test/responses/response_with_ampersands.xml
148
154
  - test/responses/response_with_ampersands.xml.base64
155
+ - test/responses/response_with_multiple_attribute_statements.xml
156
+ - test/responses/response_with_multiple_attribute_values.xml
149
157
  - test/responses/simple_saml_php.xml
150
158
  - test/responses/starfield_response.xml.base64
151
159
  - test/responses/wrapped_response_2.xml.base64