saml2 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +13 -0
  3. data/app/views/saml2/http_post.html.erb +14 -0
  4. data/lib/saml2.rb +9 -0
  5. data/lib/saml2/assertion.rb +37 -0
  6. data/lib/saml2/attribute.rb +127 -0
  7. data/lib/saml2/attribute/x500.rb +79 -0
  8. data/lib/saml2/attribute_consuming_service.rb +76 -0
  9. data/lib/saml2/authn_request.rb +116 -0
  10. data/lib/saml2/authn_statement.rb +26 -0
  11. data/lib/saml2/base.rb +53 -0
  12. data/lib/saml2/contact.rb +50 -0
  13. data/lib/saml2/endpoint.rb +46 -0
  14. data/lib/saml2/engine.rb +4 -0
  15. data/lib/saml2/entity.rb +84 -0
  16. data/lib/saml2/identity_provider.rb +57 -0
  17. data/lib/saml2/indexed_object.rb +59 -0
  18. data/lib/saml2/key.rb +46 -0
  19. data/lib/saml2/name_id.rb +60 -0
  20. data/lib/saml2/namespaces.rb +21 -0
  21. data/lib/saml2/organization.rb +74 -0
  22. data/lib/saml2/organization_and_contacts.rb +35 -0
  23. data/lib/saml2/profiles.rb +7 -0
  24. data/lib/saml2/response.rb +92 -0
  25. data/lib/saml2/role.rb +53 -0
  26. data/lib/saml2/schemas.rb +18 -0
  27. data/lib/saml2/service_provider.rb +30 -0
  28. data/lib/saml2/sso.rb +36 -0
  29. data/lib/saml2/subject.rb +49 -0
  30. data/lib/saml2/version.rb +3 -0
  31. data/schemas/saml-schema-assertion-2.0.xsd +283 -0
  32. data/schemas/saml-schema-metadata-2.0.xsd +339 -0
  33. data/schemas/saml-schema-protocol-2.0.xsd +302 -0
  34. data/schemas/xenc-schema.xsd +136 -0
  35. data/schemas/xml.xsd +287 -0
  36. data/schemas/xmldsig-core-schema.xsd +309 -0
  37. data/spec/fixtures/authnrequest.xml +12 -0
  38. data/spec/fixtures/calculated.txt +1 -0
  39. data/spec/fixtures/certificate.pem +25 -0
  40. data/spec/fixtures/entities.xml +13 -0
  41. data/spec/fixtures/privatekey.key +27 -0
  42. data/spec/fixtures/response_signed.xml +47 -0
  43. data/spec/fixtures/response_with_attribute_signed.xml +47 -0
  44. data/spec/fixtures/service_provider.xml +79 -0
  45. data/spec/fixtures/xmlsec.txt +1 -0
  46. data/spec/lib/attribute_consuming_service_spec.rb +74 -0
  47. data/spec/lib/attribute_spec.rb +39 -0
  48. data/spec/lib/authn_request_spec.rb +52 -0
  49. data/spec/lib/entity_spec.rb +45 -0
  50. data/spec/lib/identity_provider_spec.rb +23 -0
  51. data/spec/lib/indexed_object_spec.rb +38 -0
  52. data/spec/lib/response_spec.rb +60 -0
  53. data/spec/lib/service_provider_spec.rb +30 -0
  54. data/spec/spec_helper.rb +6 -0
  55. metadata +191 -0
@@ -0,0 +1,21 @@
1
+ module SAML2
2
+ module Namespaces
3
+ DSIG = "http://www.w3.org/2000/09/xmldsig#".freeze
4
+ METADATA = "urn:oasis:names:tc:SAML:2.0:metadata".freeze
5
+ SAML = "urn:oasis:names:tc:SAML:2.0:assertion".freeze
6
+ SAMLP = "urn:oasis:names:tc:SAML:2.0:protocol".freeze
7
+ XENC = "http://www.w3.org/2001/04/xmlenc#".freeze
8
+ XSI = "http://www.w3.org/2001/XMLSchema-instance".freeze
9
+ X500 = "urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500".freeze
10
+
11
+ ALL = {
12
+ 'dsig' => DSIG,
13
+ 'md' => METADATA,
14
+ 'saml' => SAML,
15
+ 'samlp' => SAMLP,
16
+ 'x500' => X500,
17
+ 'xenc' => XENC,
18
+ 'xsi' => XSI
19
+ }.freeze
20
+ end
21
+ end
@@ -0,0 +1,74 @@
1
+ require 'saml2/namespaces'
2
+
3
+ module SAML2
4
+ class Organization
5
+ def self.from_xml(node)
6
+ return nil unless node
7
+
8
+ new(nodes_to_hash(node.xpath('md:OrganizationName', Namespaces::ALL)),
9
+ nodes_to_hash(node.xpath('md:OrganizationDisplayName', Namespaces::ALL)),
10
+ nodes_to_hash(node.xpath('md:OrganizationURL', Namespaces::ALL)))
11
+ end
12
+
13
+ def initialize(name, display_name, url)
14
+ if !name.is_a?(Hash)
15
+ name = { nil => name}
16
+ end
17
+ if !display_name.is_a?(Hash)
18
+ display_name = { nil => display_name }
19
+ end
20
+ if !url.is_a?(Hash)
21
+ url = { nil => url }
22
+ end
23
+
24
+ @name, @display_name, @url = name, display_name, url
25
+ end
26
+
27
+ def name(lang = nil)
28
+ self.class.localized_name(@name, lang)
29
+ end
30
+
31
+ def display_name(lang = nil)
32
+ self.class.localized_name(@display_name, lang)
33
+ end
34
+
35
+ def url(lang = nil)
36
+ self.class.localized_name(@url, lang)
37
+ end
38
+
39
+ def build(builder)
40
+ builder['md'].Organization do |builder|
41
+ self.class.build(builder, @name, 'OrganizationName')
42
+ self.class.build(builder, @display_name, 'OrganizationDisplayName')
43
+ self.class.build(builder, @url, 'OrganizationURL')
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def self.build(builder, hash, element)
50
+ hash.each do |lang, value|
51
+ builder['md'].__send__(element, value, 'xml:lang' => lang)
52
+ end
53
+ end
54
+
55
+ def self.nodes_to_hash(nodes)
56
+ hash = {}
57
+ nodes.each do |node|
58
+ hash[node['xml:lang'].to_sym] = node.content && node.content.strip
59
+ end
60
+ hash
61
+ end
62
+
63
+ def self.localized_name(hash, lang)
64
+ case lang
65
+ when :all
66
+ hash
67
+ when nil
68
+ !hash.empty? && hash.first.last
69
+ else
70
+ hash[lang.to_sym]
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,35 @@
1
+ require 'saml2/contact'
2
+ require 'saml2/organization'
3
+
4
+ module SAML2
5
+ module OrganizationAndContacts
6
+ attr_writer :organization, :contacts
7
+
8
+ def initialize(node = nil)
9
+ unless node
10
+ @organization = nil
11
+ @contacts = []
12
+ end
13
+ end
14
+
15
+ def organization
16
+ unless instance_variable_defined?(:@organization)
17
+ @organization = Organization.from_xml(@root.at_xpath('md:Organization', Namespaces::ALL))
18
+ end
19
+ @organization
20
+ end
21
+
22
+ def contacts
23
+ @contacts ||= load_object_array(@root, 'md:ContactPerson', Contact)
24
+ end
25
+
26
+ protected
27
+
28
+ def build(builder)
29
+ organization.build(builder) if organization
30
+ contacts.each do |contact|
31
+ contact.build(builder)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,7 @@
1
+ module SAML2
2
+ module Profiles
3
+ # http://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf
4
+ WEB_BROWSER_SSO = 'urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser'.freeze
5
+ INTEROPERABLE = 'http://saml2int.org/profile'.freeze
6
+ end
7
+ end
@@ -0,0 +1,92 @@
1
+ require 'nokogiri-xmlsec'
2
+ require 'securerandom'
3
+ require 'time'
4
+
5
+ require 'saml2/assertion'
6
+ require 'saml2/authn_statement'
7
+ require 'saml2/base'
8
+ require 'saml2/subject'
9
+
10
+ module SAML2
11
+ class Response < Base
12
+ module Status
13
+ SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success".freeze
14
+ end
15
+
16
+ attr_reader :id, :issue_instant, :assertions
17
+ attr_accessor :issuer, :in_response_to, :destination, :status_code
18
+
19
+ def self.respond_to(authn_request, issuer, name_id, attributes = nil)
20
+ response = initiate(nil, issuer, name_id)
21
+ response.in_response_to = authn_request.id
22
+ response.destination = authn_request.assertion_consumer_service.location
23
+ confirmation = response.assertions.first.subject.confirmation
24
+ confirmation.in_response_to = authn_request.id
25
+ confirmation.recipient = response.destination
26
+ if attributes && authn_request.attribute_consuming_service
27
+ statement = authn_request.attribute_consuming_service.create_statement(attributes)
28
+ response.assertions.first.statements << statement if statement
29
+ end
30
+ response
31
+ end
32
+
33
+ def self.initiate(service_provider, issuer, name_id, attributes = nil)
34
+ response = new
35
+ response.issuer = issuer
36
+ response.destination = service_provider.assertion_consumer_services.default.location if service_provider
37
+ assertion = Assertion.new
38
+ assertion.subject = Subject.new
39
+ assertion.subject.name_id = name_id
40
+ assertion.subject.confirmation = Subject::Confirmation.new
41
+ assertion.subject.confirmation.method = Subject::Confirmation::Methods::BEARER
42
+ assertion.subject.confirmation.not_before = Time.now.utc
43
+ assertion.subject.confirmation.not_on_or_after = Time.now.utc + 30
44
+ assertion.subject.confirmation.recipient = response.destination if response.destination
45
+ assertion.issuer = issuer
46
+ authn_statement = AuthnStatement.new
47
+ authn_statement.authn_instant = response.issue_instant
48
+ authn_statement.authn_context_class_ref = AuthnStatement::Classes::UNSPECIFIED
49
+ assertion.statements << authn_statement
50
+ if attributes && service_provider.attribute_consuming_services.default
51
+ statement = service_provider.attribute_consuming_services.default.create_statement(attributes)
52
+ assertion.statements << statement if statement
53
+ end
54
+ response.assertions << assertion
55
+ response
56
+ end
57
+
58
+ def initialize
59
+ @id = "_#{SecureRandom.uuid}"
60
+ @status_code = Status::SUCCESS
61
+ @issue_instant = Time.now.utc
62
+ @assertions = []
63
+ end
64
+
65
+ def sign(*args)
66
+ assertions.each { |assertion| assertion.sign(*args) }
67
+ end
68
+
69
+ private
70
+ def build(builder)
71
+ builder['samlp'].Response(
72
+ 'xmlns:samlp' => Namespaces::SAMLP,
73
+ ID: id,
74
+ Version: '2.0',
75
+ IssueInstant: issue_instant.iso8601,
76
+ Destination: destination
77
+ ) do |builder|
78
+ builder.parent['InResponseTo'] = in_response_to if in_response_to
79
+
80
+ issuer.build(builder, element: 'Issuer', include_namespace: true) if issuer
81
+
82
+ builder['samlp'].Status do |builder|
83
+ builder['samlp'].StatusCode(Value: status_code)
84
+ end
85
+
86
+ assertions.each do |assertion|
87
+ builder.parent << assertion.to_xml
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
data/lib/saml2/role.rb ADDED
@@ -0,0 +1,53 @@
1
+ require 'set'
2
+
3
+ require 'saml2/base'
4
+ require 'saml2/organization_and_contacts'
5
+ require 'saml2/key'
6
+
7
+ module SAML2
8
+ class Role < Base
9
+ module Protocols
10
+ SAML2 = 'urn:oasis:names:tc:SAML:2.0:protocol'.freeze
11
+ end
12
+
13
+ include OrganizationAndContacts
14
+
15
+ attr_writer :supported_protocols, :keys
16
+
17
+ def initialize(node = nil)
18
+ super
19
+ @root = node
20
+ unless @root
21
+ @supported_protocols = Set.new
22
+ @supported_protocols << Protocols::SAML2
23
+ @keys = []
24
+ end
25
+ end
26
+
27
+ def supported_protocols
28
+ @supported_protocols ||= @root['protocolSupportEnumeration'].split
29
+ end
30
+
31
+ def keys
32
+ @keys ||= load_object_array(@root, 'md:KeyDescriptor', Key)
33
+ end
34
+
35
+ def signing_keys
36
+ keys.select { |key| key.signing? }
37
+ end
38
+
39
+ def encryption_keys
40
+ keys.select { |key| key.encryption? }
41
+ end
42
+
43
+ protected
44
+ # should be called from inside the role element
45
+ def build(builder)
46
+ builder.parent['protocolSupportEnumeration'] = supported_protocols.to_a.join(' ')
47
+ keys.each do |key|
48
+ key.build(builder)
49
+ end
50
+ super
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,18 @@
1
+ module SAML2
2
+ module Schemas
3
+ def self.metadata
4
+ @metadata ||= schema('saml-schema-metadata-2.0.xsd')
5
+ end
6
+
7
+ def self.protocol
8
+ @protocol ||= schema('saml-schema-protocol-2.0.xsd')
9
+ end
10
+
11
+ private
12
+ def self.schema(filename)
13
+ Dir.chdir(File.expand_path(File.join(__FILE__, '../../../schemas'))) do
14
+ Nokogiri::XML::Schema(File.read(filename))
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ require 'nokogiri'
2
+
3
+ require 'saml2/endpoint'
4
+ require 'saml2/sso'
5
+
6
+ module SAML2
7
+ class ServiceProvider < SSO
8
+ class << self
9
+ alias_method :from_xml, :new
10
+ end
11
+
12
+ def initialize(root)
13
+ @root = root
14
+ end
15
+
16
+ def assertion_consumer_services
17
+ @assertion_consumer_services ||= begin
18
+ nodes = @root.xpath('md:AssertionConsumerService', Namespaces::ALL)
19
+ Endpoint::Indexed::Array.from_xml(nodes)
20
+ end
21
+ end
22
+
23
+ def attribute_consuming_services
24
+ @attribute_consuming_services ||= begin
25
+ nodes = @root.xpath('md:AttributeConsumingService', Namespaces::ALL)
26
+ AttributeConsumingService::Array.from_xml(nodes)
27
+ end
28
+ end
29
+ end
30
+ end
data/lib/saml2/sso.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'saml2/role'
2
+
3
+ module SAML2
4
+ class SSO < Role
5
+ attr_reader :single_logout_services, :name_id_formats
6
+
7
+ def initialize(node = nil)
8
+ super
9
+ unless node
10
+ @single_logout_services = []
11
+ @name_id_formats = []
12
+ end
13
+ end
14
+
15
+ def single_logout_services
16
+ @single_logout_services ||= load_object_array(@root, 'md:SingleLogoutService', Endpoint)
17
+ end
18
+
19
+ def name_id_formats
20
+ @name_id_formats ||= load_string_array(@root, 'md:NameIDFormat')
21
+ end
22
+
23
+ protected
24
+ # should be called from inside the role element
25
+ def build(builder)
26
+ super
27
+
28
+ single_logout_services.each do |slo|
29
+ slo.build(builder, 'SingleLogoutService')
30
+ end
31
+ name_id_formats.each do |nif|
32
+ builder['md'].NameIDFormat(nif)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,49 @@
1
+ require 'saml2/name_id'
2
+ require 'saml2/namespaces'
3
+
4
+ module SAML2
5
+ class Subject
6
+ attr_accessor :name_id, :confirmation
7
+
8
+ def self.from_xml(node)
9
+ return nil unless node
10
+ subject = new
11
+ subject.name_id = NameID.from_xml(node.at_xpath('saml:NameID', Namespaces::ALL))
12
+
13
+ subject
14
+ end
15
+
16
+ def build(builder)
17
+ builder['saml'].Subject do |builder|
18
+ name_id.build(builder) if name_id
19
+ confirmation.build(builder) if confirmation
20
+ end
21
+ end
22
+
23
+ class Confirmation
24
+ module Methods
25
+ BEARER = 'urn:oasis:names:tc:SAML:2.0:cm:bearer'.freeze
26
+ HOLDER_OF_KEY = 'urn:oasis:names:tc:SAML:2.0:cm:holder-of-key'.freeze
27
+ SENDER_VOUCHES = 'urn:oasis:names:tc:SAML:2.0:cm:sender-vouches'.freeze
28
+ end
29
+
30
+ attr_accessor :method, :not_before, :not_on_or_after, :recipient, :in_response_to
31
+
32
+ def build(builder)
33
+ builder['saml'].SubjectConfirmation('Method' => method) do |builder|
34
+ if in_response_to ||
35
+ recipient ||
36
+ not_before ||
37
+ not_on_or_after
38
+ builder['saml'].SubjectConfirmationData do |builder|
39
+ builder.parent['NotBefore'] = not_before.iso8601 if not_before
40
+ builder.parent['NotOnOrAfter'] = not_on_or_after.iso8601 if not_on_or_after
41
+ builder.parent['Recipient'] = recipient if recipient
42
+ builder.parent['InResponseTo'] = in_response_to if in_response_to
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module SAML2
2
+ VERSION = '1.0.0'
3
+ end
@@ -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-core-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>