Skip to content

Commit 3e7a9a9

Browse files
author
Lordnibbler
committed
Merge pull request #122 from borgand/multiple-attribute-values
Fixes #112 and #117 in a backwards compatible manner
2 parents 9dee0ea + deb7be1 commit 3e7a9a9

5 files changed

Lines changed: 112 additions & 3 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module OneLogin
2+
module RubySaml
3+
4+
# Wrapper for AttributeValue with multiple values
5+
# It is subclass of String to be backwards compatible
6+
# Use AttributeValue#values to get all values as an array
7+
class AttributeValue < String
8+
attr_accessor :values
9+
def initialize(str="", values=[])
10+
@values = values
11+
super(str)
12+
end
13+
end
14+
end
15+
end

lib/onelogin/ruby-saml/response.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ def sessionindex
4848
end
4949
end
5050

51-
# A hash of alle the attributes with the response. Assuming there is only one value for each key
51+
# A hash of all the attributes with the response.
52+
# Multiple values will be returned in the AttributeValue#values array
53+
# in reverse order, when compared to XML
5254
def attributes
5355
@attr_statements ||= begin
5456
result = {}
@@ -58,9 +60,16 @@ def attributes
5860

5961
stmt_element.elements.each do |attr_element|
6062
name = attr_element.attributes["Name"]
61-
value = attr_element.elements.first.text
63+
values = attr_element.elements.collect(&:text)
6264

63-
result[name] = value
65+
# Set up a string-like wrapper for the values array
66+
attr_value = AttributeValue.new(values.first, values.reverse)
67+
# Merge values if the Attribute has already been seen
68+
if result[name]
69+
attr_value.values += result[name].values
70+
end
71+
72+
result[name] = attr_value
6473
end
6574

6675
result.keys.each do |key|

lib/ruby-saml.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
require 'onelogin/ruby-saml/authrequest'
33
require 'onelogin/ruby-saml/logoutrequest'
44
require 'onelogin/ruby-saml/logoutresponse'
5+
require 'onelogin/ruby-saml/attribute_value'
56
require 'onelogin/ruby-saml/response'
67
require 'onelogin/ruby-saml/settings'
78
require 'onelogin/ruby-saml/validation_error'

test/response_test.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,33 @@ class RubySamlTest < Test::Unit::TestCase
223223
response = OneLogin::RubySaml::Response.new(response_document_4)
224224
assert_equal Hash.new, response.attributes
225225
end
226+
227+
context "#multiple values" do
228+
should "extract single value as string" do
229+
response = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
230+
assert_equal "demo", response.attributes[:uid]
231+
end
232+
233+
should "extract first of multiple values as string for b/w compatibility" do
234+
response = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
235+
assert_equal 'value1', response.attributes[:another_value]
236+
end
237+
238+
should "return array with all attributes when asked" do
239+
response = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
240+
assert_equal ['value2', 'value1'], response.attributes[:another_value].values
241+
end
242+
243+
should "return last of multiple values when multiple Attribute tags in XML" do
244+
response = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
245+
assert_equal 'role2', response.attributes[:role]
246+
end
247+
248+
should "return all of multiple values in reverse order when multiple Attribute tags in XML" do
249+
response = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
250+
assert_equal ['role2', 'role1'], response.attributes[:role].values
251+
end
252+
end
226253
end
227254

228255
context "#session_expires_at" do
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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:Attribute>
55+
</saml:AttributeStatement>
56+
</saml:Assertion>
57+
</samlp:Response>

0 commit comments

Comments
 (0)