ruby-saml 0.8.5 → 0.8.6

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.

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