ruby-samlnechotech 0.7.23

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 (51) hide show
  1. data/.document +5 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +13 -0
  5. data/LICENSE +19 -0
  6. data/README.md +128 -0
  7. data/Rakefile +41 -0
  8. data/lib/onelogin/ruby-samlnechotech/authrequest.rb +84 -0
  9. data/lib/onelogin/ruby-samlnechotech/logging.rb +26 -0
  10. data/lib/onelogin/ruby-samlnechotech/logoutrequest.rb +82 -0
  11. data/lib/onelogin/ruby-samlnechotech/logoutresponse.rb +154 -0
  12. data/lib/onelogin/ruby-samlnechotech/metadata.rb +66 -0
  13. data/lib/onelogin/ruby-samlnechotech/response.rb +186 -0
  14. data/lib/onelogin/ruby-samlnechotech/settings.rb +27 -0
  15. data/lib/onelogin/ruby-samlnechotech/validation_error.rb +7 -0
  16. data/lib/onelogin/ruby-samlnechotech/version.rb +5 -0
  17. data/lib/ruby-samlnechotech.rb +9 -0
  18. data/lib/schemas/saml20assertion_schema.xsd +283 -0
  19. data/lib/schemas/saml20protocol_schema.xsd +302 -0
  20. data/lib/schemas/xenc_schema.xsd +146 -0
  21. data/lib/schemas/xmldsig_schema.xsd +318 -0
  22. data/lib/xml_security.rb +169 -0
  23. data/ruby-samlnechotech.gemspec +29 -0
  24. data/test/certificates/certificate1 +12 -0
  25. data/test/certificates/r1_certificate2_base64 +1 -0
  26. data/test/logoutrequest_test.rb +111 -0
  27. data/test/logoutresponse_test.rb +116 -0
  28. data/test/request_test.rb +97 -0
  29. data/test/response_test.rb +247 -0
  30. data/test/responses/adfs_response_sha1.xml +46 -0
  31. data/test/responses/adfs_response_sha256.xml +46 -0
  32. data/test/responses/adfs_response_sha384.xml +46 -0
  33. data/test/responses/adfs_response_sha512.xml +46 -0
  34. data/test/responses/logoutresponse_fixtures.rb +67 -0
  35. data/test/responses/no_signature_ns.xml +48 -0
  36. data/test/responses/open_saml_response.xml +56 -0
  37. data/test/responses/r1_response6.xml.base64 +1 -0
  38. data/test/responses/response1.xml.base64 +1 -0
  39. data/test/responses/response2.xml.base64 +79 -0
  40. data/test/responses/response3.xml.base64 +66 -0
  41. data/test/responses/response4.xml.base64 +93 -0
  42. data/test/responses/response5.xml.base64 +102 -0
  43. data/test/responses/response_with_ampersands.xml +139 -0
  44. data/test/responses/response_with_ampersands.xml.base64 +93 -0
  45. data/test/responses/simple_saml_php.xml +71 -0
  46. data/test/responses/starfield_response.xml.base64 +1 -0
  47. data/test/responses/wrapped_response_2.xml.base64 +150 -0
  48. data/test/settings_test.rb +46 -0
  49. data/test/test_helper.rb +75 -0
  50. data/test/xml_security_test.rb +160 -0
  51. metadata +172 -0
@@ -0,0 +1,66 @@
1
+ require "rexml/document"
2
+ require "rexml/xpath"
3
+ require "uri"
4
+
5
+ # Class to return SP metadata based on the settings requested.
6
+ # Return this XML in a controller, then give that URL to the the
7
+ # IdP administrator. The IdP will poll the URL and your settings
8
+ # will be updated automatically
9
+ module Onelogin
10
+ module Saml
11
+ include REXML
12
+ class Metadata
13
+ def generate(settings)
14
+ meta_doc = REXML::Document.new
15
+ root = meta_doc.add_element "md:EntityDescriptor", {
16
+ "xmlns:md" => "urn:oasis:names:tc:SAML:2.0:metadata"
17
+ }
18
+ sp_sso = root.add_element "md:SPSSODescriptor", {
19
+ "protocolSupportEnumeration" => "urn:oasis:names:tc:SAML:2.0:protocol",
20
+ # Metadata request need not be signed (as we don't publish our cert)
21
+ "AuthnRequestsSigned" => false,
22
+ # However we would like assertions signed if idp_cert_fingerprint or idp_cert is set
23
+ "WantAssertionsSigned" => (!settings.idp_cert_fingerprint.nil? || !settings.idp_cert.nil?)
24
+ }
25
+ if settings.issuer != nil
26
+ root.attributes["entityID"] = settings.issuer
27
+ end
28
+ if settings.assertion_consumer_logout_service_url != nil
29
+ sp_sso.add_element "md:SingleLogoutService", {
30
+ # Add this as a setting to create different bindings?
31
+ "Binding" => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
32
+ "Location" => settings.assertion_consumer_logout_service_url,
33
+ "ResponseLocation" => settings.assertion_consumer_logout_service_url,
34
+ "isDefault" => true,
35
+ "index" => 0
36
+ }
37
+ end
38
+ if settings.name_identifier_format != nil
39
+ name_id = sp_sso.add_element "md:NameIDFormat"
40
+ name_id.text = settings.name_identifier_format
41
+ end
42
+ if settings.assertion_consumer_service_url != nil
43
+ sp_sso.add_element "md:AssertionConsumerService", {
44
+ # Add this as a setting to create different bindings?
45
+ "Binding" => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
46
+ "Location" => settings.assertion_consumer_service_url,
47
+ "isDefault" => true,
48
+ "index" => 0
49
+ }
50
+ end
51
+ # With OpenSSO, it might be required to also include
52
+ # <md:RoleDescriptor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:query="urn:oasis:names:tc:SAML:metadata:ext:query" xsi:type="query:AttributeQueryDescriptorType" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"/>
53
+ # <md:XACMLAuthzDecisionQueryDescriptor WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"/>
54
+
55
+ meta_doc << REXML::XMLDecl.new
56
+ ret = ""
57
+ # pretty print the XML so IdP administrators can easily see what the SP supports
58
+ meta_doc.write(ret, 1)
59
+
60
+ Logging.debug "Generated metadata:\n#{ret}"
61
+
62
+ ret
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,186 @@
1
+ require "xml_security"
2
+ require "time"
3
+ require "nokogiri"
4
+
5
+ # Only supports SAML 2.0
6
+ module Onelogin
7
+ module Saml
8
+
9
+ class Response
10
+ ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
11
+ PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
12
+ DSIG = "http://www.w3.org/2000/09/xmldsig#"
13
+
14
+ # TODO: This should probably be ctor initialized too... WDYT?
15
+ attr_accessor :settings
16
+
17
+ attr_reader :options
18
+ attr_reader :response
19
+ attr_reader :document
20
+
21
+ def initialize(response, options = {})
22
+ raise ArgumentError.new("Response cannot be nil") if response.nil?
23
+ @options = options
24
+ @response = (response =~ /^</) ? response : Base64.decode64(response)
25
+ @document = XMLSecurity::SignedDocument.new(@response)
26
+ end
27
+
28
+ def is_valid?
29
+ validate
30
+ end
31
+
32
+ def validate!
33
+ validate(false)
34
+ end
35
+
36
+ # The value of the user identifier as designated by the initialization request response
37
+ def name_id
38
+ @name_id ||= begin
39
+ node = xpath_first_from_signed_assertion('/a:Subject/a:NameID')
40
+ node.nil? ? nil : node.text
41
+ end
42
+ end
43
+
44
+ def sessionindex
45
+ @sessionindex ||= begin
46
+ node = xpath_first_from_signed_assertion('/a:AuthnStatement')
47
+ node.nil? ? nil : node.attributes['SessionIndex']
48
+ end
49
+ end
50
+
51
+ # A hash of alle the attributes with the response. Assuming there is only one value for each key
52
+ def attributes
53
+ @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 = attr_element.elements.first.text
62
+
63
+ result[name] = value
64
+ end
65
+
66
+ result.keys.each do |key|
67
+ result[key.intern] = result[key]
68
+ end
69
+
70
+ result
71
+ end
72
+ end
73
+
74
+ # When this user session should expire at latest
75
+ def session_expires_at
76
+ @expires_at ||= begin
77
+ node = xpath_first_from_signed_assertion('/a:AuthnStatement')
78
+ parse_time(node, "SessionNotOnOrAfter")
79
+ end
80
+ end
81
+
82
+ # Checks the status of the response for a "Success" code
83
+ def success?
84
+ @status_code ||= begin
85
+ node = REXML::XPath.first(document, "/p:Response/p:Status/p:StatusCode", { "p" => PROTOCOL, "a" => ASSERTION })
86
+ node.attributes["Value"] == "urn:oasis:names:tc:SAML:2.0:status:Success"
87
+ end
88
+ end
89
+
90
+ # Conditions (if any) for the assertion to run
91
+ def conditions
92
+ @conditions ||= xpath_first_from_signed_assertion('/a:Conditions')
93
+ end
94
+
95
+ def issuer
96
+ @issuer ||= begin
97
+ node = REXML::XPath.first(document, "/p:Response/a:Issuer", { "p" => PROTOCOL, "a" => ASSERTION })
98
+ node ||= xpath_first_from_signed_assertion('/a:Issuer')
99
+ node.nil? ? nil : node.text
100
+ end
101
+ end
102
+
103
+ private
104
+
105
+ def validation_error(message)
106
+ raise ValidationError.new(message)
107
+ end
108
+
109
+ def validate(soft = true)
110
+ validate_structure(soft) &&
111
+ validate_response_state(soft) &&
112
+ validate_conditions(soft) &&
113
+ document.validate(get_fingerprint, soft) &&
114
+ success?
115
+ end
116
+
117
+ def validate_structure(soft = true)
118
+ Dir.chdir(File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'schemas'))) do
119
+ @schema = Nokogiri::XML::Schema(IO.read('saml20protocol_schema.xsd'))
120
+ @xml = Nokogiri::XML(self.document.to_s)
121
+ end
122
+ if soft
123
+ @schema.validate(@xml).map{ return false }
124
+ else
125
+ @schema.validate(@xml).map{ |error| validation_error("#{error.message}\n\n#{@xml.to_s}") }
126
+ end
127
+ end
128
+
129
+ def validate_response_state(soft = true)
130
+ if response.empty?
131
+ return soft ? false : validation_error("Blank response")
132
+ end
133
+
134
+ if settings.nil?
135
+ return soft ? false : validation_error("No settings on response")
136
+ end
137
+
138
+ if settings.idp_cert_fingerprint.nil? && settings.idp_cert.nil?
139
+ return soft ? false : validation_error("No fingerprint or certificate on settings")
140
+ end
141
+
142
+ true
143
+ end
144
+
145
+ def xpath_first_from_signed_assertion(subelt=nil)
146
+ node = REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{document.signed_element_id}']#{subelt}", { "p" => PROTOCOL, "a" => ASSERTION })
147
+ node ||= REXML::XPath.first(document, "/p:Response[@ID='#{document.signed_element_id}']/a:Assertion#{subelt}", { "p" => PROTOCOL, "a" => ASSERTION })
148
+ node
149
+ end
150
+
151
+ def get_fingerprint
152
+ if settings.idp_cert
153
+ cert = OpenSSL::X509::Certificate.new(settings.idp_cert)
154
+ Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":")
155
+ else
156
+ settings.idp_cert_fingerprint
157
+ end
158
+ end
159
+
160
+ def validate_conditions(soft = true)
161
+ return true if conditions.nil?
162
+ return true if options[:skip_conditions]
163
+
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
168
+ end
169
+
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
174
+ end
175
+
176
+ true
177
+ end
178
+
179
+ def parse_time(node, attribute)
180
+ if node && node.attributes[attribute]
181
+ Time.parse(node.attributes[attribute])
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,27 @@
1
+ module Onelogin
2
+ module Saml
3
+ class Settings
4
+ def initialize(overrides = {})
5
+ config = DEFAULTS.merge(overrides)
6
+ config.each do |k,v|
7
+ acc = "#{k.to_s}=".to_sym
8
+ self.send(acc, v) if self.respond_to? acc
9
+ end
10
+ end
11
+ attr_accessor :assertion_consumer_service_url, :issuer, :sp_name_qualifier
12
+ attr_accessor :idp_sso_target_url, :idp_cert_fingerprint, :idp_cert, :name_identifier_format
13
+ attr_accessor :authn_context
14
+ attr_accessor :idp_slo_target_url
15
+ attr_accessor :name_identifier_value
16
+ attr_accessor :sessionindex
17
+ attr_accessor :assertion_consumer_logout_service_url
18
+ attr_accessor :compress_request
19
+ attr_accessor :double_quote_xml_attribute_values
20
+ attr_accessor :passive
21
+
22
+ private
23
+
24
+ DEFAULTS = {:compress_request => true, :double_quote_xml_attribute_values => false}
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ module Onelogin
2
+ module Saml
3
+ class ValidationError < StandardError
4
+ end
5
+ end
6
+ end
7
+
@@ -0,0 +1,5 @@
1
+ module Onelogin
2
+ module Saml
3
+ VERSION = '0.7.23'
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ require 'onelogin/ruby-samlnechotech/logging'
2
+ require 'onelogin/ruby-samlnechotech/authrequest'
3
+ require 'onelogin/ruby-samlnechotech/logoutrequest'
4
+ require 'onelogin/ruby-samlnechotech/logoutresponse'
5
+ require 'onelogin/ruby-samlnechotech/response'
6
+ require 'onelogin/ruby-samlnechotech/settings'
7
+ require 'onelogin/ruby-samlnechotech/validation_error'
8
+ require 'onelogin/ruby-samlnechotech/metadata'
9
+ require 'onelogin/ruby-samlnechotech/version'
@@ -0,0 +1,283 @@
1
+ <?xml version="1.0" encoding="US-ASCII"?>
2
+ <schema
3
+ targetNamespace="urn:oasis:names:tc:SAML:2.0:assertion"
4
+ xmlns="http://www.w3.org/2001/XMLSchema"
5
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
6
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
7
+ xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
8
+ elementFormDefault="unqualified"
9
+ attributeFormDefault="unqualified"
10
+ blockDefault="substitution"
11
+ version="2.0">
12
+ <import namespace="http://www.w3.org/2000/09/xmldsig#"
13
+ schemaLocation="xmldsig_schema.xsd"/>
14
+ <import namespace="http://www.w3.org/2001/04/xmlenc#"
15
+ schemaLocation="xenc_schema.xsd"/>
16
+ <annotation>
17
+ <documentation>
18
+ Document identifier: saml-schema-assertion-2.0
19
+ Location: http://docs.oasis-open.org/security/saml/v2.0/
20
+ Revision history:
21
+ V1.0 (November, 2002):
22
+ Initial Standard Schema.
23
+ V1.1 (September, 2003):
24
+ Updates within the same V1.0 namespace.
25
+ V2.0 (March, 2005):
26
+ New assertion schema for SAML V2.0 namespace.
27
+ </documentation>
28
+ </annotation>
29
+ <attributeGroup name="IDNameQualifiers">
30
+ <attribute name="NameQualifier" type="string" use="optional"/>
31
+ <attribute name="SPNameQualifier" type="string" use="optional"/>
32
+ </attributeGroup>
33
+ <element name="BaseID" type="saml:BaseIDAbstractType"/>
34
+ <complexType name="BaseIDAbstractType" abstract="true">
35
+ <attributeGroup ref="saml:IDNameQualifiers"/>
36
+ </complexType>
37
+ <element name="NameID" type="saml:NameIDType"/>
38
+ <complexType name="NameIDType">
39
+ <simpleContent>
40
+ <extension base="string">
41
+ <attributeGroup ref="saml:IDNameQualifiers"/>
42
+ <attribute name="Format" type="anyURI" use="optional"/>
43
+ <attribute name="SPProvidedID" type="string" use="optional"/>
44
+ </extension>
45
+ </simpleContent>
46
+ </complexType>
47
+ <complexType name="EncryptedElementType">
48
+ <sequence>
49
+ <element ref="xenc:EncryptedData"/>
50
+ <element ref="xenc:EncryptedKey" minOccurs="0" maxOccurs="unbounded"/>
51
+ </sequence>
52
+ </complexType>
53
+ <element name="EncryptedID" type="saml:EncryptedElementType"/>
54
+ <element name="Issuer" type="saml:NameIDType"/>
55
+ <element name="AssertionIDRef" type="NCName"/>
56
+ <element name="AssertionURIRef" type="anyURI"/>
57
+ <element name="Assertion" type="saml:AssertionType"/>
58
+ <complexType name="AssertionType">
59
+ <sequence>
60
+ <element ref="saml:Issuer"/>
61
+ <element ref="ds:Signature" minOccurs="0"/>
62
+ <element ref="saml:Subject" minOccurs="0"/>
63
+ <element ref="saml:Conditions" minOccurs="0"/>
64
+ <element ref="saml:Advice" minOccurs="0"/>
65
+ <choice minOccurs="0" maxOccurs="unbounded">
66
+ <element ref="saml:Statement"/>
67
+ <element ref="saml:AuthnStatement"/>
68
+ <element ref="saml:AuthzDecisionStatement"/>
69
+ <element ref="saml:AttributeStatement"/>
70
+ </choice>
71
+ </sequence>
72
+ <attribute name="Version" type="string" use="required"/>
73
+ <attribute name="ID" type="ID" use="required"/>
74
+ <attribute name="IssueInstant" type="dateTime" use="required"/>
75
+ </complexType>
76
+ <element name="Subject" type="saml:SubjectType"/>
77
+ <complexType name="SubjectType">
78
+ <choice>
79
+ <sequence>
80
+ <choice>
81
+ <element ref="saml:BaseID"/>
82
+ <element ref="saml:NameID"/>
83
+ <element ref="saml:EncryptedID"/>
84
+ </choice>
85
+ <element ref="saml:SubjectConfirmation" minOccurs="0" maxOccurs="unbounded"/>
86
+ </sequence>
87
+ <element ref="saml:SubjectConfirmation" maxOccurs="unbounded"/>
88
+ </choice>
89
+ </complexType>
90
+ <element name="SubjectConfirmation" type="saml:SubjectConfirmationType"/>
91
+ <complexType name="SubjectConfirmationType">
92
+ <sequence>
93
+ <choice minOccurs="0">
94
+ <element ref="saml:BaseID"/>
95
+ <element ref="saml:NameID"/>
96
+ <element ref="saml:EncryptedID"/>
97
+ </choice>
98
+ <element ref="saml:SubjectConfirmationData" minOccurs="0"/>
99
+ </sequence>
100
+ <attribute name="Method" type="anyURI" use="required"/>
101
+ </complexType>
102
+ <element name="SubjectConfirmationData" type="saml:SubjectConfirmationDataType"/>
103
+ <complexType name="SubjectConfirmationDataType" mixed="true">
104
+ <complexContent>
105
+ <restriction base="anyType">
106
+ <sequence>
107
+ <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
108
+ </sequence>
109
+ <attribute name="NotBefore" type="dateTime" use="optional"/>
110
+ <attribute name="NotOnOrAfter" type="dateTime" use="optional"/>
111
+ <attribute name="Recipient" type="anyURI" use="optional"/>
112
+ <attribute name="InResponseTo" type="NCName" use="optional"/>
113
+ <attribute name="Address" type="string" use="optional"/>
114
+ <anyAttribute namespace="##other" processContents="lax"/>
115
+ </restriction>
116
+ </complexContent>
117
+ </complexType>
118
+ <complexType name="KeyInfoConfirmationDataType" mixed="false">
119
+ <complexContent>
120
+ <restriction base="saml:SubjectConfirmationDataType">
121
+ <sequence>
122
+ <element ref="ds:KeyInfo" maxOccurs="unbounded"/>
123
+ </sequence>
124
+ </restriction>
125
+ </complexContent>
126
+ </complexType>
127
+ <element name="Conditions" type="saml:ConditionsType"/>
128
+ <complexType name="ConditionsType">
129
+ <choice minOccurs="0" maxOccurs="unbounded">
130
+ <element ref="saml:Condition"/>
131
+ <element ref="saml:AudienceRestriction"/>
132
+ <element ref="saml:OneTimeUse"/>
133
+ <element ref="saml:ProxyRestriction"/>
134
+ </choice>
135
+ <attribute name="NotBefore" type="dateTime" use="optional"/>
136
+ <attribute name="NotOnOrAfter" type="dateTime" use="optional"/>
137
+ </complexType>
138
+ <element name="Condition" type="saml:ConditionAbstractType"/>
139
+ <complexType name="ConditionAbstractType" abstract="true"/>
140
+ <element name="AudienceRestriction" type="saml:AudienceRestrictionType"/>
141
+ <complexType name="AudienceRestrictionType">
142
+ <complexContent>
143
+ <extension base="saml:ConditionAbstractType">
144
+ <sequence>
145
+ <element ref="saml:Audience" maxOccurs="unbounded"/>
146
+ </sequence>
147
+ </extension>
148
+ </complexContent>
149
+ </complexType>
150
+ <element name="Audience" type="anyURI"/>
151
+ <element name="OneTimeUse" type="saml:OneTimeUseType" />
152
+ <complexType name="OneTimeUseType">
153
+ <complexContent>
154
+ <extension base="saml:ConditionAbstractType"/>
155
+ </complexContent>
156
+ </complexType>
157
+ <element name="ProxyRestriction" type="saml:ProxyRestrictionType"/>
158
+ <complexType name="ProxyRestrictionType">
159
+ <complexContent>
160
+ <extension base="saml:ConditionAbstractType">
161
+ <sequence>
162
+ <element ref="saml:Audience" minOccurs="0" maxOccurs="unbounded"/>
163
+ </sequence>
164
+ <attribute name="Count" type="nonNegativeInteger" use="optional"/>
165
+ </extension>
166
+ </complexContent>
167
+ </complexType>
168
+ <element name="Advice" type="saml:AdviceType"/>
169
+ <complexType name="AdviceType">
170
+ <choice minOccurs="0" maxOccurs="unbounded">
171
+ <element ref="saml:AssertionIDRef"/>
172
+ <element ref="saml:AssertionURIRef"/>
173
+ <element ref="saml:Assertion"/>
174
+ <element ref="saml:EncryptedAssertion"/>
175
+ <any namespace="##other" processContents="lax"/>
176
+ </choice>
177
+ </complexType>
178
+ <element name="EncryptedAssertion" type="saml:EncryptedElementType"/>
179
+ <element name="Statement" type="saml:StatementAbstractType"/>
180
+ <complexType name="StatementAbstractType" abstract="true"/>
181
+ <element name="AuthnStatement" type="saml:AuthnStatementType"/>
182
+ <complexType name="AuthnStatementType">
183
+ <complexContent>
184
+ <extension base="saml:StatementAbstractType">
185
+ <sequence>
186
+ <element ref="saml:SubjectLocality" minOccurs="0"/>
187
+ <element ref="saml:AuthnContext"/>
188
+ </sequence>
189
+ <attribute name="AuthnInstant" type="dateTime" use="required"/>
190
+ <attribute name="SessionIndex" type="string" use="optional"/>
191
+ <attribute name="SessionNotOnOrAfter" type="dateTime" use="optional"/>
192
+ </extension>
193
+ </complexContent>
194
+ </complexType>
195
+ <element name="SubjectLocality" type="saml:SubjectLocalityType"/>
196
+ <complexType name="SubjectLocalityType">
197
+ <attribute name="Address" type="string" use="optional"/>
198
+ <attribute name="DNSName" type="string" use="optional"/>
199
+ </complexType>
200
+ <element name="AuthnContext" type="saml:AuthnContextType"/>
201
+ <complexType name="AuthnContextType">
202
+ <sequence>
203
+ <choice>
204
+ <sequence>
205
+ <element ref="saml:AuthnContextClassRef"/>
206
+ <choice minOccurs="0">
207
+ <element ref="saml:AuthnContextDecl"/>
208
+ <element ref="saml:AuthnContextDeclRef"/>
209
+ </choice>
210
+ </sequence>
211
+ <choice>
212
+ <element ref="saml:AuthnContextDecl"/>
213
+ <element ref="saml:AuthnContextDeclRef"/>
214
+ </choice>
215
+ </choice>
216
+ <element ref="saml:AuthenticatingAuthority" minOccurs="0" maxOccurs="unbounded"/>
217
+ </sequence>
218
+ </complexType>
219
+ <element name="AuthnContextClassRef" type="anyURI"/>
220
+ <element name="AuthnContextDeclRef" type="anyURI"/>
221
+ <element name="AuthnContextDecl" type="anyType"/>
222
+ <element name="AuthenticatingAuthority" type="anyURI"/>
223
+ <element name="AuthzDecisionStatement" type="saml:AuthzDecisionStatementType"/>
224
+ <complexType name="AuthzDecisionStatementType">
225
+ <complexContent>
226
+ <extension base="saml:StatementAbstractType">
227
+ <sequence>
228
+ <element ref="saml:Action" maxOccurs="unbounded"/>
229
+ <element ref="saml:Evidence" minOccurs="0"/>
230
+ </sequence>
231
+ <attribute name="Resource" type="anyURI" use="required"/>
232
+ <attribute name="Decision" type="saml:DecisionType" use="required"/>
233
+ </extension>
234
+ </complexContent>
235
+ </complexType>
236
+ <simpleType name="DecisionType">
237
+ <restriction base="string">
238
+ <enumeration value="Permit"/>
239
+ <enumeration value="Deny"/>
240
+ <enumeration value="Indeterminate"/>
241
+ </restriction>
242
+ </simpleType>
243
+ <element name="Action" type="saml:ActionType"/>
244
+ <complexType name="ActionType">
245
+ <simpleContent>
246
+ <extension base="string">
247
+ <attribute name="Namespace" type="anyURI" use="required"/>
248
+ </extension>
249
+ </simpleContent>
250
+ </complexType>
251
+ <element name="Evidence" type="saml:EvidenceType"/>
252
+ <complexType name="EvidenceType">
253
+ <choice maxOccurs="unbounded">
254
+ <element ref="saml:AssertionIDRef"/>
255
+ <element ref="saml:AssertionURIRef"/>
256
+ <element ref="saml:Assertion"/>
257
+ <element ref="saml:EncryptedAssertion"/>
258
+ </choice>
259
+ </complexType>
260
+ <element name="AttributeStatement" type="saml:AttributeStatementType"/>
261
+ <complexType name="AttributeStatementType">
262
+ <complexContent>
263
+ <extension base="saml:StatementAbstractType">
264
+ <choice maxOccurs="unbounded">
265
+ <element ref="saml:Attribute"/>
266
+ <element ref="saml:EncryptedAttribute"/>
267
+ </choice>
268
+ </extension>
269
+ </complexContent>
270
+ </complexType>
271
+ <element name="Attribute" type="saml:AttributeType"/>
272
+ <complexType name="AttributeType">
273
+ <sequence>
274
+ <element ref="saml:AttributeValue" minOccurs="0" maxOccurs="unbounded"/>
275
+ </sequence>
276
+ <attribute name="Name" type="string" use="required"/>
277
+ <attribute name="NameFormat" type="anyURI" use="optional"/>
278
+ <attribute name="FriendlyName" type="string" use="optional"/>
279
+ <anyAttribute namespace="##other" processContents="lax"/>
280
+ </complexType>
281
+ <element name="AttributeValue" type="anyType" nillable="true"/>
282
+ <element name="EncryptedAttribute" type="saml:EncryptedElementType"/>
283
+ </schema>