rsaml 0.1.2

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.
Files changed (97) hide show
  1. data/LICENSE +0 -0
  2. data/README +13 -0
  3. data/Rakefile +136 -0
  4. data/lib/rsaml.rb +57 -0
  5. data/lib/rsaml/action.rb +57 -0
  6. data/lib/rsaml/action_namespace.rb +63 -0
  7. data/lib/rsaml/advice.rb +34 -0
  8. data/lib/rsaml/assertion.rb +192 -0
  9. data/lib/rsaml/attribute.rb +76 -0
  10. data/lib/rsaml/audience.rb +19 -0
  11. data/lib/rsaml/authentication_context.rb +34 -0
  12. data/lib/rsaml/authn_context/README +1 -0
  13. data/lib/rsaml/authn_context/authentication_context_declaration.rb +42 -0
  14. data/lib/rsaml/authn_context/identification.rb +10 -0
  15. data/lib/rsaml/authn_context/physical_verification.rb +24 -0
  16. data/lib/rsaml/condition.rb +13 -0
  17. data/lib/rsaml/conditions.rb +107 -0
  18. data/lib/rsaml/encrypted.rb +12 -0
  19. data/lib/rsaml/errors.rb +16 -0
  20. data/lib/rsaml/evidence.rb +21 -0
  21. data/lib/rsaml/ext/string.rb +5 -0
  22. data/lib/rsaml/identifier.rb +9 -0
  23. data/lib/rsaml/identifier/base.rb +23 -0
  24. data/lib/rsaml/identifier/issuer.rb +28 -0
  25. data/lib/rsaml/identifier/name.rb +55 -0
  26. data/lib/rsaml/parser.rb +23 -0
  27. data/lib/rsaml/protocol.rb +21 -0
  28. data/lib/rsaml/protocol/artifact_resolve.rb +14 -0
  29. data/lib/rsaml/protocol/assertion_id_request.rb +18 -0
  30. data/lib/rsaml/protocol/authn_request.rb +91 -0
  31. data/lib/rsaml/protocol/idp_entry.rb +18 -0
  32. data/lib/rsaml/protocol/idp_list.rb +28 -0
  33. data/lib/rsaml/protocol/message.rb +65 -0
  34. data/lib/rsaml/protocol/name_id_policy.rb +31 -0
  35. data/lib/rsaml/protocol/query.rb +12 -0
  36. data/lib/rsaml/protocol/query/attribute_query.rb +56 -0
  37. data/lib/rsaml/protocol/query/authn_query.rb +30 -0
  38. data/lib/rsaml/protocol/query/authz_decision_query.rb +40 -0
  39. data/lib/rsaml/protocol/query/subject_query.rb +22 -0
  40. data/lib/rsaml/protocol/request.rb +27 -0
  41. data/lib/rsaml/protocol/requested_authn_context.rb +34 -0
  42. data/lib/rsaml/protocol/response.rb +56 -0
  43. data/lib/rsaml/protocol/scoping.rb +33 -0
  44. data/lib/rsaml/protocol/status.rb +38 -0
  45. data/lib/rsaml/protocol/status_code.rb +84 -0
  46. data/lib/rsaml/proxy_restriction.rb +30 -0
  47. data/lib/rsaml/statement.rb +10 -0
  48. data/lib/rsaml/statement/attribute_statement.rb +27 -0
  49. data/lib/rsaml/statement/authentication_statement.rb +57 -0
  50. data/lib/rsaml/statement/authorization_decision_statement.rb +53 -0
  51. data/lib/rsaml/statement/base.rb +9 -0
  52. data/lib/rsaml/subject.rb +37 -0
  53. data/lib/rsaml/subject_confirmation.rb +35 -0
  54. data/lib/rsaml/subject_confirmation_data.rb +55 -0
  55. data/lib/rsaml/subject_locality.rb +27 -0
  56. data/lib/rsaml/validatable.rb +21 -0
  57. data/lib/rsaml/version.rb +9 -0
  58. data/lib/xml_enc.rb +3 -0
  59. data/lib/xml_sig.rb +11 -0
  60. data/lib/xml_sig/canonicalization_method.rb +43 -0
  61. data/lib/xml_sig/key_info.rb +55 -0
  62. data/lib/xml_sig/reference.rb +57 -0
  63. data/lib/xml_sig/signature.rb +29 -0
  64. data/lib/xml_sig/signature_method.rb +20 -0
  65. data/lib/xml_sig/signed_info.rb +27 -0
  66. data/lib/xml_sig/transform.rb +37 -0
  67. data/test/action_namespace_test.rb +93 -0
  68. data/test/action_test.rb +51 -0
  69. data/test/advice_test.rb +25 -0
  70. data/test/assertion_test.rb +192 -0
  71. data/test/attribute_test.rb +60 -0
  72. data/test/authentication_context_test.rb +26 -0
  73. data/test/conditions_test.rb +84 -0
  74. data/test/evidence_test.rb +33 -0
  75. data/test/identifier_test.rb +22 -0
  76. data/test/issuer_test.rb +33 -0
  77. data/test/name_test.rb +33 -0
  78. data/test/parser_test.rb +32 -0
  79. data/test/protocol/assertion_id_request_test.rb +19 -0
  80. data/test/protocol/attribute_query_test.rb +30 -0
  81. data/test/protocol/authn_query_test.rb +20 -0
  82. data/test/protocol/authn_request_test.rb +56 -0
  83. data/test/protocol/authz_decision_query_test.rb +31 -0
  84. data/test/protocol/idp_list_test.rb +15 -0
  85. data/test/protocol/request_test.rb +66 -0
  86. data/test/protocol/response_test.rb +68 -0
  87. data/test/protocol/scoping_test.rb +20 -0
  88. data/test/protocol/status_code_test.rb +34 -0
  89. data/test/protocol/status_test.rb +16 -0
  90. data/test/proxy_restriction_test.rb +20 -0
  91. data/test/rsaml_test.rb +12 -0
  92. data/test/statement_test.rb +101 -0
  93. data/test/subject_locality_test.rb +27 -0
  94. data/test/subject_test.rb +44 -0
  95. data/test/test_helper.rb +16 -0
  96. data/test/xml_sig/canonicalization_test.rb +19 -0
  97. metadata +187 -0
@@ -0,0 +1,29 @@
1
+ module XmlSig #:nodoc:
2
+ # An XML signature.
3
+ class Signature
4
+ attr_accessor :id
5
+ attr_accessor :signed_info
6
+ attr_accessor :signature_value
7
+ attr_accessor :key_info
8
+
9
+ def objects
10
+ @objects ||= []
11
+ end
12
+
13
+ def assert
14
+ # raise AssertionError, "An assertion signature must be valid"
15
+ end
16
+
17
+ # Construct an XML fragment representing the signature
18
+ def to_xml(xml=Builder::XmlMarkup.new)
19
+ attributes = {}
20
+ attributes['Id'] = id unless id.nil?
21
+ attributes['xmlns:ds'] = "http://www.w3.org/2000/09/xmldsig#"
22
+ xml.tag!('ds:Signature', attributes) {
23
+ xml << signed_info.to_xml if signed_info
24
+ xml.tag!('ds:SignatureValue')
25
+ xml.tag!('ds:KeyInfo') if key_info
26
+ }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ module XmlSig #:nodoc:
2
+ # SignatureMethod is a required element that specifies the algorithm used for
3
+ # signature generation and validation. This algorithm identifies all cryptographic
4
+ # functions involved in the signature operation (e.g. hashing, public key
5
+ # algorithms, MACs, padding, etc.).
6
+ class SignatureMethod
7
+ attr_accessor :algorithm
8
+
9
+ def validate
10
+ raise ValidationError, "Algorithm is required" if algorithm.nil?
11
+ end
12
+
13
+ def to_xml(xml=Builder::XmlMarkup.new)
14
+ attributes = {'Algorightm' => algorithm}
15
+ xml.tag!('ds:SignatureMethod', attributes) {
16
+ xml.tag!('ds:HMACOutputLength', hmac_output_length) unless hmac_output_length.nil?
17
+ }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ module XmlSig #:nodoc:
2
+ class SignedInfo
3
+ attr_accessor :id
4
+ attr_accessor :canonicalization_method
5
+ attr_accessor :signature_method
6
+
7
+ def references
8
+ @references ||= []
9
+ end
10
+
11
+ def validate
12
+ raise ValidationError, "Canonicalization method is required" if canonicalization_method.nil?
13
+ raise ValidationError, "Signature method is required" if signature_method.nil?
14
+ raise ValidationError, "At least one reference is required" if references.empty?
15
+ end
16
+
17
+ def to_xml(xml=Builder::XmlMarkup.new)
18
+ attributes = {}
19
+ attributes['Id'] = id unless id.nil?
20
+ xml.tag!('ds:SignedInfo', attributes) {
21
+ xml << canonicalization_method.to_xml unless canonicalization_method.nil?
22
+ xml << signature_method.to_xml unless signature_method.nil?
23
+ references.each { |reference| xml << reference.to_xml }
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ module XmlSig #:nodoc:
2
+ class Transform
3
+ attr_accessor :algorithm
4
+ attr_accessor :xpath
5
+
6
+ def to_xml(xml=Builder::XmlMarkup.new)
7
+ attributes = {'Algorightm' => algorithm}
8
+ xml.tag!('ds:Transform', attributes) {
9
+ xml.tag!('ds:XPath', xpath) unless xpath.nil?
10
+ }
11
+ end
12
+ end
13
+ class Base64Transform
14
+ IDENTIFIER = 'http://www.w3.org/2000/09/xmldsig#base64'
15
+ def process(content)
16
+ content # TODO: implement
17
+ end
18
+ end
19
+ class XPathFiltering
20
+ IDENTIFIER = 'http://www.w3.org/TR/1999/REC-xpath-19991116'
21
+ def process(content)
22
+ content # TODO: implement
23
+ end
24
+ end
25
+ class EnvelopedSignatureTransform
26
+ IDENTIFIER = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'
27
+ def process(content)
28
+ content # TODO: implement
29
+ end
30
+ end
31
+ class XSLTTransform
32
+ IDENTIFIER = 'http://www.w3.org/TR/1999/REC-xslt-19991116'
33
+ def process(content)
34
+ content # TODO: implement
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,93 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ActionNamespaceTest < Test::Unit::TestCase
4
+ context "the ActionNamespace class" do
5
+ should "define all of the namespaces in the SAML 2.0 specification" do
6
+ namespace_uris = ActionNamespace.namespaces.values.collect { |ns| ns.uri }
7
+ assert namespace_uris.include?('urn:oasis:names:tc:SAML:1.0:action:rwedc')
8
+ assert namespace_uris.include?('urn:oasis:names:tc:SAML:1.0:action:rwedc-negation')
9
+ assert namespace_uris.include?('urn:oasis:names:tc:SAML:1.0:action:ghpp')
10
+ assert namespace_uris.include?('urn:oasis:names:tc:SAML:1.0:action:unix')
11
+ end
12
+ should "return a namespace instance given a URI" do
13
+ assert_equal(ActionNamespace.namespaces[:rwedc],
14
+ ActionNamespace.namespace_for_uri('urn:oasis:names:tc:SAML:1.0:action:rwedc')
15
+ )
16
+ assert_equal(ActionNamespace.namespaces[:rwedc_negation],
17
+ ActionNamespace.namespace_for_uri('urn:oasis:names:tc:SAML:1.0:action:rwedc-negation')
18
+ )
19
+ end
20
+ end
21
+ context "the rwdec namespace" do
22
+ setup do
23
+ @action_namespace = ActionNamespace.namespaces[:rwedc]
24
+ @expected_actions = ['Read','Write','Execute','Delete','Control']
25
+ end
26
+ should "have the correct uri" do
27
+ assert_equal 'urn:oasis:names:tc:SAML:1.0:action:rwedc', @action_namespace.uri
28
+ end
29
+ should "return the uri when to_s is invoked" do
30
+ assert_equal @action_namespace.uri, @action_namespace.to_s
31
+ end
32
+ should "have the correct actions" do
33
+ assert_equal @expected_actions, @action_namespace.action_names
34
+ end
35
+ should "return true for a valid action" do
36
+ @expected_actions.each do |action|
37
+ assert @action_namespace.valid_action?(action)
38
+ end
39
+ end
40
+ should "return false for an invalid action" do
41
+ assert_equal false, @action_namespace.valid_action?('invalid-action')
42
+ end
43
+ end
44
+ context "the rwdec-negation namespace" do
45
+ setup do
46
+ @action_namespace = ActionNamespace.namespaces[:rwedc_negation]
47
+ @expected_actions = [
48
+ 'Read','Write','Execute','Delete','Control',
49
+ '~Read','~Write','~Execute','~Delete','~Control'
50
+ ]
51
+ end
52
+ should "have the correct uri" do
53
+ assert_equal 'urn:oasis:names:tc:SAML:1.0:action:rwedc-negation', @action_namespace.uri
54
+ end
55
+ should "have the correct actions" do
56
+ assert_equal @expected_actions, @action_namespace.action_names
57
+ end
58
+ should "return true for a valid action" do
59
+ @expected_actions.each do |action|
60
+ assert @action_namespace.valid_action?(action)
61
+ end
62
+ end
63
+ should "return false for an invalid action" do
64
+ assert_equal false, @action_namespace.valid_action?('invalid-action')
65
+ end
66
+ end
67
+ context "the ghpp namespace" do
68
+ setup do
69
+ @action_namespace = ActionNamespace.namespaces[:ghpp]
70
+ @expected_actions = ['GET','HEAD','PUT','POST']
71
+ end
72
+ should "have the correct uri" do
73
+ assert_equal 'urn:oasis:names:tc:SAML:1.0:action:ghpp', @action_namespace.uri
74
+ end
75
+ should "have the correct actions" do
76
+ assert_equal @expected_actions, @action_namespace.action_names
77
+ end
78
+ should "return false for an invalid action" do
79
+ assert_equal false, @action_namespace.valid_action?('invalid-action')
80
+ end
81
+ end
82
+ context "the unix file permissions namespace" do
83
+ setup do
84
+ @action_namespace = ActionNamespace.namespaces[:unix]
85
+ end
86
+ should "have the correct uri" do
87
+ assert_equal 'urn:oasis:names:tc:SAML:1.0:action:unix', @action_namespace.uri
88
+ end
89
+ should_eventually "have the correct actions" do
90
+
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,51 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ActionTest < Test::Unit::TestCase
4
+ context "an action" do
5
+ setup do
6
+ @action = Action.new('Read')
7
+ end
8
+ should "have the rwedc_negation namespace by default" do
9
+ assert_equal Action.namespaces[:rwedc_negation], @action.namespace
10
+ end
11
+ should "be valid by default" do
12
+ assert @action.valid?
13
+ end
14
+ context "when producing xml" do
15
+ should "optionally have a namespace" do
16
+ assert_match(/<saml:Action Namespace="#{@action.namespace}"/, @action.to_xml)
17
+ end
18
+ end
19
+ context "when consuming xml" do
20
+ should "return a valid Action instance" do
21
+ action = Action.from_xml('<saml:Action xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">Read</saml:Action>')
22
+ assert_not_nil(action)
23
+ assert_equal 'Read', action.value
24
+ assert_equal Action.namespaces[:rwedc_negation], action.namespace
25
+ assert action.valid?
26
+ end
27
+ context "with an action namespace attribute" do
28
+ should "return a valid Action instance with an action namespace" do
29
+ action = Action.from_xml(%Q(<saml:Action xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Namespace="#{Action.namespaces[:rwedc]}">Write</saml:Action>))
30
+ assert_not_nil(action)
31
+ assert_equal 'Write', action.value
32
+ assert_equal Action.namespaces[:rwedc], action.namespace
33
+ end
34
+ end
35
+ end
36
+ context "when validating" do
37
+ should "raise an error if no value is provided" do
38
+ assert_raise ValidationError do
39
+ @action.value = nil
40
+ @action.validate
41
+ end
42
+ end
43
+ should "raise an error if the value is not in the specified namespace" do
44
+ assert_raise ValidationError do
45
+ @action.value = 'PUT'
46
+ @action.validate
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class AdviceTest < Test::Unit::TestCase
4
+ context "an advice" do
5
+ setup { @advice = Advice.new }
6
+ should "have 0 assertions by default" do
7
+ assert @advice.assertions.empty?
8
+ end
9
+ should "be valid if all assertions are valid" do
10
+ assert @advice.valid?
11
+ end
12
+ context "when producing xml" do
13
+ should "produce an empty advice tag when there are no assertions" do
14
+ assert_match(/<saml:Advice><\/saml:Advice>/, @advice.to_xml)
15
+ end
16
+ end
17
+ context "when consuming xml" do
18
+ should "return a valid Advice instance" do
19
+ advice = Advice.from_xml('<saml:Advice xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"></saml:Advice>')
20
+ assert_not_nil(advice)
21
+ assert advice.valid?
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,192 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class AssertionTest < Test::Unit::TestCase
4
+ context "an assertion" do
5
+ setup do
6
+ @issuer = Identifier::Issuer.new('example')
7
+ @assertion = Assertion.new(@issuer)
8
+ end
9
+ should "require version of 2.0" do
10
+ assert_equal "2.0", @assertion.version
11
+ end
12
+ should "require ID" do
13
+ assert_not_nil @assertion.id
14
+ end
15
+ should "require issue instant" do
16
+ assert_not_nil @assertion.issue_instant
17
+ end
18
+ should "require an issuer" do
19
+ assert_not_nil @assertion.issuer
20
+ end
21
+
22
+ context "with only a subject" do
23
+ setup do
24
+ @assertion.subject = 'test'
25
+ end
26
+ should "be valid" do
27
+ assert_nothing_raised do
28
+ @assertion.validate
29
+ end
30
+ end
31
+ end
32
+ context "with an authentication statement" do
33
+ setup do
34
+ @assertion.statements << AuthenticationStatement.new(AuthenticationContext.new)
35
+ end
36
+ should "require a subject" do
37
+ assert_raise ValidationError do
38
+ @assertion.validate
39
+ end
40
+ assert !@assertion.valid?
41
+ end
42
+ end
43
+ context "with an attribute statement" do
44
+ setup do
45
+ @assertion.statements << AttributeStatement.new
46
+ end
47
+ should "require a subject" do
48
+ assert_raise ValidationError do
49
+ @assertion.validate
50
+ end
51
+ end
52
+ end
53
+ context "with a authorization decision statement" do
54
+ setup do
55
+ @assertion.statements << AuthorizationDecisionStatement.new
56
+ end
57
+ should "require a subject" do
58
+ assert_raise ValidationError do
59
+ @assertion.validate
60
+ end
61
+ end
62
+ end
63
+
64
+ context "when producing xml" do
65
+ # TODO: implement tests for XML results
66
+ should "always include version, id and issue instant attributes and an issuer child element" do
67
+ xml = @assertion.to_xml
68
+ assert_match(/^<saml:Assertion/, xml)
69
+ assert_match(/Version="2.0"/, xml)
70
+ assert_match(/ID="#{uuid_match}"/, xml)
71
+ assert_match(/IssueInstant="#{date_match}"/, xml)
72
+ assert_match(/<saml:Issuer/, xml)
73
+ end
74
+ should "optionally include a signature" do
75
+ @assertion.signature = XmlSig::Signature.new
76
+ xml = @assertion.to_xml
77
+ assert_match(/<ds:Signature/, xml)
78
+ end
79
+ should "optionally include a subject" do
80
+ @assertion.subject = Subject.new(Identifier::Name.new('The Subject'))
81
+ xml = @assertion.to_xml
82
+ assert_match(%Q(<saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">The Subject</saml:NameID></saml:Subject>), xml)
83
+ end
84
+ should "optionally include conditions" do
85
+ @assertion.conditions << Condition.new
86
+ xml = @assertion.to_xml
87
+ assert_match(/<saml:Conditions>/, xml)
88
+ end
89
+ should "optionally include advice" do
90
+ uri = 'http://example.com/some_advice'
91
+ advice = Advice.new
92
+ advice.assertions << AssertionIDRef.new(UUID.new.generate)
93
+ advice.assertions << AssertionURIRef.new(uri) # a URI
94
+ @assertion.advice << advice
95
+ xml = @assertion.to_xml
96
+ assert_match(/<saml:Advice><saml:AssertionIDRef>#{uuid_match}<\/saml:AssertionIDRef>/, xml)
97
+ assert_match(/<saml:AssertionURIRef>#{uri}<\/saml:AssertionURIRef><\/saml:Advice>/, xml)
98
+ end
99
+ should "optionally include statements" do
100
+ @assertion.statements << AuthenticationStatement.new(AuthenticationContext.new)
101
+ xml = @assertion.to_xml
102
+ assert_match(/<saml:AuthnStatement AuthnInstant="#{date_match}"/, xml)
103
+ end
104
+ end
105
+
106
+ context "when consuming xml" do
107
+ should "return a valid Assertion instance" do
108
+ xml_fragment = %Q(
109
+ <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
110
+ <saml:Issuer>Example</saml:Issuer>
111
+ <saml:Subject>Anthony</saml:Subject>
112
+ </saml:Assertion>
113
+ )
114
+ assertion = Assertion.from_xml(xml_fragment)
115
+ assert_not_nil assertion
116
+ assert_not_nil assertion.issuer
117
+ assert_equal 'Example', assertion.issuer.value
118
+ assert_nothing_raised do
119
+ assertion.validate
120
+ end
121
+ end
122
+ context "where there is no saml:Subject element" do
123
+ should "raise a validation error" do
124
+ xml_fragment = %Q(
125
+ <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
126
+ <saml:Issuer>Example</saml:Issuer>
127
+ </saml:Assertion>
128
+ )
129
+ assertion = Assertion.from_xml(xml_fragment)
130
+ assert_raise ValidationError do
131
+ assertion.validate
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ context "an assertion URI ref" do
138
+ setup do
139
+ @assertion_uri_ref = AssertionURIRef.new('some_uri')
140
+ end
141
+ should "provide a uri accessor" do
142
+ assert_equal 'some_uri', @assertion_uri_ref.uri
143
+ end
144
+ context "when validating" do
145
+ should "raise an error if no uri is provided" do
146
+ assert_raise ValidationError do
147
+ @assertion_uri_ref.uri = nil
148
+ @assertion_uri_ref.validate
149
+ end
150
+ end
151
+ end
152
+ context "when producing xml" do
153
+ should "have the uri as the value" do
154
+ assert_match(/<saml:AssertionURIRef>some_uri<\/saml:AssertionURIRef>/, @assertion_uri_ref.to_xml)
155
+ end
156
+ end
157
+ context "when consuming xml" do
158
+ should "return a valid AssertionURIRef instance" do
159
+ assertion_ref = AssertionURIRef.from_xml('<saml:AssertionURIRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">some_uri</saml:AssertionURIRef>')
160
+ assert_not_nil assertion_ref
161
+ assert_equal 'some_uri', assertion_ref.uri
162
+ assert assertion_ref.valid?
163
+ end
164
+ end
165
+ end
166
+ context "an assertion ID ref" do
167
+ setup do
168
+ @assertion_id_ref = AssertionIDRef.new('some_id')
169
+ end
170
+ context "when validating" do
171
+ should "raise an error if no id is provided" do
172
+ assert_raise ValidationError do
173
+ @assertion_id_ref.id = nil
174
+ @assertion_id_ref.validate
175
+ end
176
+ end
177
+ end
178
+ context "when producing xml" do
179
+ should "have an id as the value" do
180
+ assert_match(/<saml:AssertionIDRef>some_id<\/saml:AssertionIDRef>/, @assertion_id_ref.to_xml)
181
+ end
182
+ end
183
+ context "when consuming xml" do
184
+ should "return a valid AssertionIDRef instance" do
185
+ assertion_ref = AssertionIDRef.from_xml('<saml:AssertionIDRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">some_id</saml:AssertionIDRef>')
186
+ assert_not_nil assertion_ref
187
+ assert_equal 'some_id', assertion_ref.id
188
+ assert assertion_ref.valid?
189
+ end
190
+ end
191
+ end
192
+ end