ruby-saml-federa 0.0.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.
- data/.document +5 -0
- data/.gitignore +10 -0
- data/.travis.yml +5 -0
- data/Gemfile +12 -0
- data/LICENSE +19 -0
- data/README.md +124 -0
- data/Rakefile +41 -0
- data/lib/federa/ruby-saml/authrequest.rb +181 -0
- data/lib/federa/ruby-saml/coding.rb +34 -0
- data/lib/federa/ruby-saml/logging.rb +26 -0
- data/lib/federa/ruby-saml/logout_request.rb +126 -0
- data/lib/federa/ruby-saml/logout_response.rb +132 -0
- data/lib/federa/ruby-saml/metadata.rb +266 -0
- data/lib/federa/ruby-saml/request.rb +81 -0
- data/lib/federa/ruby-saml/response.rb +203 -0
- data/lib/federa/ruby-saml/settings.rb +28 -0
- data/lib/federa/ruby-saml/validation_error.rb +7 -0
- data/lib/federa/ruby-saml/version.rb +5 -0
- data/lib/ruby-saml-federa.rb +11 -0
- data/lib/schemas/saml20assertion_schema.xsd +283 -0
- data/lib/schemas/saml20protocol_schema.xsd +302 -0
- data/lib/schemas/xenc_schema.xsd +146 -0
- data/lib/schemas/xmldsig_schema.xsd +318 -0
- data/lib/xml_security.rb +165 -0
- data/ruby-saml-federa.gemspec +21 -0
- data/test/certificates/certificate1 +12 -0
- data/test/logoutrequest_test.rb +98 -0
- data/test/request_test.rb +53 -0
- data/test/response_test.rb +219 -0
- data/test/responses/adfs_response_sha1.xml +46 -0
- data/test/responses/adfs_response_sha256.xml +46 -0
- data/test/responses/adfs_response_sha384.xml +46 -0
- data/test/responses/adfs_response_sha512.xml +46 -0
- data/test/responses/no_signature_ns.xml +48 -0
- data/test/responses/open_saml_response.xml +56 -0
- data/test/responses/response1.xml.base64 +1 -0
- data/test/responses/response2.xml.base64 +79 -0
- data/test/responses/response3.xml.base64 +66 -0
- data/test/responses/response4.xml.base64 +93 -0
- data/test/responses/response5.xml.base64 +102 -0
- data/test/responses/response_with_ampersands.xml +139 -0
- data/test/responses/response_with_ampersands.xml.base64 +93 -0
- data/test/responses/simple_saml_php.xml +71 -0
- data/test/responses/wrapped_response_2.xml.base64 +150 -0
- data/test/settings_test.rb +43 -0
- data/test/test_helper.rb +66 -0
- data/test/xml_security_test.rb +123 -0
- metadata +155 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
|
2
|
+
# A few helper functions for assembling a SAMLRequest and
|
3
|
+
# sending it to the IdP
|
4
|
+
module Federa::Saml
|
5
|
+
include Coding
|
6
|
+
module Request
|
7
|
+
|
8
|
+
# a few symbols for SAML class names
|
9
|
+
HTTP_POST = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
10
|
+
HTTP_GET = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
|
11
|
+
# get the IdP metadata, and select the appropriate SSO binding
|
12
|
+
# that we can support. Currently this is HTTP-Redirect and HTTP-POST
|
13
|
+
# but more could be added in the future
|
14
|
+
def binding_select(service)
|
15
|
+
# first check if we're still using the old hard coded method for
|
16
|
+
# backwards compatability
|
17
|
+
if @settings.idp_metadata == nil && @settings.idp_sso_target_url != nil
|
18
|
+
@URL = @settings.idp_sso_target_url
|
19
|
+
return "GET", content_get
|
20
|
+
end
|
21
|
+
# grab the metadata
|
22
|
+
metadata = Metadata::new
|
23
|
+
meta_doc = metadata.get_idp_metadata(@settings)
|
24
|
+
|
25
|
+
# first try POST
|
26
|
+
sso_element = REXML::XPath.first(meta_doc,
|
27
|
+
"/EntityDescriptor/IDPSSODescriptor/#{service}[@Binding='#{HTTP_POST}']")
|
28
|
+
if sso_element
|
29
|
+
@URL = sso_element.attributes["Location"]
|
30
|
+
#Logging.debug "binding_select: POST to #{@URL}"
|
31
|
+
return "POST", content_post
|
32
|
+
end
|
33
|
+
|
34
|
+
# next try GET
|
35
|
+
sso_element = REXML::XPath.first(meta_doc,
|
36
|
+
"/EntityDescriptor/IDPSSODescriptor/#{service}[@Binding='#{HTTP_GET}']")
|
37
|
+
if sso_element
|
38
|
+
@URL = sso_element.attributes["Location"]
|
39
|
+
Logging.debug "binding_select: GET from #{@URL}"
|
40
|
+
return "GET", content_get
|
41
|
+
end
|
42
|
+
# other types we might want to add in the future: SOAP, Artifact
|
43
|
+
end
|
44
|
+
|
45
|
+
# construct the the parameter list on the URL and return
|
46
|
+
def content_get
|
47
|
+
# compress GET requests to try and stay under that 8KB request limit
|
48
|
+
deflated_request = Zlib::Deflate.deflate(@request, 9)[2..-5]
|
49
|
+
# strict_encode64() isn't available? sub out the newlines
|
50
|
+
@request_params["SAMLRequest"] = Base64.encode64(deflated_request).gsub(/\n/, "")
|
51
|
+
|
52
|
+
Logging.debug "SAMLRequest=#{@request_params["SAMLRequest"]}"
|
53
|
+
uri = Addressable::URI.parse(@URL)
|
54
|
+
uri.query_values = @request_params
|
55
|
+
url = uri.to_s
|
56
|
+
#url = @URL + "?SAMLRequest=" + @request_params["SAMLRequest"]
|
57
|
+
Logging.debug "Sending to URL #{url}"
|
58
|
+
return url
|
59
|
+
end
|
60
|
+
# construct an HTML form (POST) and return the content
|
61
|
+
def content_post
|
62
|
+
# POST requests seem to bomb out when they're deflated
|
63
|
+
# and they probably don't need to be compressed anyway
|
64
|
+
@request_params["SAMLRequest"] = Base64.encode64(@request).gsub(/\n/, "")
|
65
|
+
|
66
|
+
#Logging.debug "SAMLRequest=#{@request_params["SAMLRequest"]}"
|
67
|
+
# kind of a cheesy method of building an HTML, form since we can't rely on Rails too much,
|
68
|
+
# and REXML doesn't work well with quote characters
|
69
|
+
str = "<html><body onLoad=\"document.getElementById('form').submit();\">\n"
|
70
|
+
str += "<form id='form' name='form' method='POST' action=\"#{@URL}\">\n"
|
71
|
+
# we could change this in the future to associate a temp auth session ID
|
72
|
+
str += "<input name='RelayState' value='ruby-saml' type='hidden' />\n"
|
73
|
+
@request_params.each_pair do |key, value|
|
74
|
+
str += "<input name=\"#{key}\" value=\"#{value}\" type='hidden' />\n"
|
75
|
+
end
|
76
|
+
str += "</form></body></html>\n"
|
77
|
+
#Logging.debug "Created form:\n#{str}"
|
78
|
+
return str
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require "xml_security"
|
2
|
+
require "time"
|
3
|
+
require "nokogiri"
|
4
|
+
require 'ruby-debug'
|
5
|
+
require "base64"
|
6
|
+
require "openssl"
|
7
|
+
require "digest/sha1"
|
8
|
+
|
9
|
+
# Only supports SAML 2.0
|
10
|
+
module Federa
|
11
|
+
module Saml
|
12
|
+
|
13
|
+
class Response
|
14
|
+
ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
|
15
|
+
PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
|
16
|
+
DSIG = "http://www.w3.org/2000/09/xmldsig#"
|
17
|
+
|
18
|
+
attr_accessor :options, :response, :document, :settings
|
19
|
+
|
20
|
+
def initialize(response, options = {})
|
21
|
+
raise ArgumentError.new("Response cannot be nil") if response.nil?
|
22
|
+
self.options = options
|
23
|
+
self.response = response
|
24
|
+
begin
|
25
|
+
self.document = XMLSecurity::SignedDocument.new(Base64.decode64(response))
|
26
|
+
rescue REXML::ParseException => e
|
27
|
+
if response =~ /</
|
28
|
+
self.document = XMLSecurity::SignedDocument.new(response)
|
29
|
+
else
|
30
|
+
raise e
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def is_valid?
|
37
|
+
validate
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate!
|
41
|
+
validate(false)
|
42
|
+
end
|
43
|
+
|
44
|
+
# The value of the user identifier as designated by the initialization request response
|
45
|
+
def name_id
|
46
|
+
@name_id ||= begin
|
47
|
+
node = REXML::XPath.first(document, "/saml2p:Response/saml2:Assertion[@ID='#{document.signed_element_id}']/saml2:Subject/saml2:NameID")
|
48
|
+
node ||= REXML::XPath.first(document, "/saml2p:Response[@ID='#{document.signed_element_id}']/saml2:Assertion/saml2:Subject/saml2:NameID")
|
49
|
+
node.nil? ? nil : node.text
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# A hash of alle the attributes with the response. Assuming there is only one value for each key
|
54
|
+
def attributes
|
55
|
+
@attr_statements ||= begin
|
56
|
+
result = {}
|
57
|
+
|
58
|
+
stmt_element = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AttributeStatement", { "p" => PROTOCOL, "a" => ASSERTION })
|
59
|
+
return {} if stmt_element.nil?
|
60
|
+
|
61
|
+
stmt_element.elements.each do |attr_element|
|
62
|
+
name = attr_element.attributes["Name"]
|
63
|
+
value = attr_element.elements.first.text
|
64
|
+
|
65
|
+
result[name] = value
|
66
|
+
end
|
67
|
+
|
68
|
+
result.keys.each do |key|
|
69
|
+
result[key.intern] = result[key]
|
70
|
+
end
|
71
|
+
|
72
|
+
result
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# When this user session should expire at latest
|
77
|
+
def session_expires_at
|
78
|
+
@expires_at ||= begin
|
79
|
+
node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AuthnStatement", { "p" => PROTOCOL, "a" => ASSERTION })
|
80
|
+
parse_time(node, "SessionNotOnOrAfter")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Checks the status of the response for a "Success" code
|
85
|
+
def success?
|
86
|
+
@status_code ||= begin
|
87
|
+
node = REXML::XPath.first(document, "/p:Response/p:Status/p:StatusCode", { "p" => PROTOCOL, "a" => ASSERTION })
|
88
|
+
node.attributes["Value"] == "urn:oasis:names:tc:SAML:2.0:status:Success"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Conditions (if any) for the assertion to run
|
93
|
+
def conditions
|
94
|
+
@conditions ||= begin
|
95
|
+
REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{document.signed_element_id}']/a:Conditions", { "p" => PROTOCOL, "a" => ASSERTION })
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def issuer
|
100
|
+
@issuer ||= begin
|
101
|
+
node = REXML::XPath.first(document, "/p:Response/a:Issuer", { "p" => PROTOCOL, "a" => ASSERTION })
|
102
|
+
node ||= REXML::XPath.first(document, "/p:Response/a:Assertion/a:Issuer", { "p" => PROTOCOL, "a" => ASSERTION })
|
103
|
+
node.nil? ? nil : node.text
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def validation_error(message)
|
110
|
+
raise ValidationError.new(message)
|
111
|
+
end
|
112
|
+
|
113
|
+
def validate(soft = true)
|
114
|
+
# prime the IdP metadata before the document validation.
|
115
|
+
# The idp_cert needs to be populated before the validate_response_state method
|
116
|
+
|
117
|
+
if settings
|
118
|
+
Federa::Saml::Metadata.new(settings).get_idp_metadata
|
119
|
+
end
|
120
|
+
return false if validate_structure(soft) == false
|
121
|
+
return false if validate_response_state(soft) == false
|
122
|
+
return false if validate_conditions(soft) == false
|
123
|
+
|
124
|
+
# Just in case a user needs to toss out the signature validation,
|
125
|
+
# I'm adding in an option for it. (Sometimes canonicalization is a bitch!)
|
126
|
+
return true if settings.skip_validation == true
|
127
|
+
|
128
|
+
# document.validte populates the idp_cert
|
129
|
+
return false if document.validate(get_fingerprint, soft) == false
|
130
|
+
|
131
|
+
# validate response code
|
132
|
+
return false if success? == false
|
133
|
+
|
134
|
+
return true
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
def validate_structure(soft = true)
|
139
|
+
Dir.chdir(File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'schemas'))) do
|
140
|
+
@schema = Nokogiri::XML::Schema(IO.read('saml20protocol_schema.xsd'))
|
141
|
+
@xml = Nokogiri::XML(self.document.to_s)
|
142
|
+
end
|
143
|
+
if soft
|
144
|
+
@schema.validate(@xml).map{ return false }
|
145
|
+
else
|
146
|
+
@schema.validate(@xml).map{ |error| raise(Exception.new("#{error.message}\n\n#{@xml.to_s}")) }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def validate_response_state(soft = true)
|
151
|
+
if response.empty?
|
152
|
+
return soft ? false : validation_error("Blank response")
|
153
|
+
end
|
154
|
+
|
155
|
+
if settings.nil?
|
156
|
+
return soft ? false : validation_error("No settings on response")
|
157
|
+
end
|
158
|
+
|
159
|
+
if settings.idp_cert_fingerprint.nil? && settings.idp_cert.nil?
|
160
|
+
return soft ? false : validation_error("No fingerprint or certificate on settings")
|
161
|
+
end
|
162
|
+
|
163
|
+
true
|
164
|
+
end
|
165
|
+
|
166
|
+
def get_fingerprint
|
167
|
+
if settings.idp_cert
|
168
|
+
cert_text = Base64.decode64(settings.idp_cert)
|
169
|
+
cert = OpenSSL::X509::Certificate.new(cert_text)
|
170
|
+
Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":")
|
171
|
+
else
|
172
|
+
settings.idp_cert_fingerprint
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
def validate_conditions(soft = true)
|
178
|
+
return true if conditions.nil?
|
179
|
+
return true if options[:skip_conditions]
|
180
|
+
|
181
|
+
if not_before = parse_time(conditions, "NotBefore")
|
182
|
+
if Time.now.utc < not_before
|
183
|
+
return soft ? false : validation_error("Current time is earlier than NotBefore condition")
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
if not_on_or_after = parse_time(conditions, "NotOnOrAfter")
|
188
|
+
if Time.now.utc >= not_on_or_after
|
189
|
+
return soft ? false : validation_error("Current time is on or after NotOnOrAfter condition")
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
true
|
194
|
+
end
|
195
|
+
|
196
|
+
def parse_time(node, attribute)
|
197
|
+
if node && node.attributes[attribute]
|
198
|
+
Time.parse(node.attributes[attribute])
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Federa
|
2
|
+
module Saml
|
3
|
+
class Settings
|
4
|
+
|
5
|
+
attr_accessor :sp_name_qualifier, :sp_cert
|
6
|
+
attr_accessor :idp_sso_target_url, :idp_cert_fingerprint, :idp_cert, :idp_slo_target_url, :idp_metadata, :idp_metadata_ttl, :idp_name_qualifier
|
7
|
+
attr_accessor :assertion_consumer_service_binding, :assertion_consumer_service_url
|
8
|
+
attr_accessor :name_identifier_value, :name_identifier_format
|
9
|
+
attr_accessor :sessionindex, :issuer, :destination_service_url, :authn_context, :requester_identificator
|
10
|
+
attr_accessor :single_logout_service_url, :single_logout_service_binding, :single_logout_destination
|
11
|
+
attr_accessor :skip_validation
|
12
|
+
|
13
|
+
def initialize(config = {})
|
14
|
+
config.each do |k,v|
|
15
|
+
acc = "#{k.to_s}=".to_sym
|
16
|
+
self.send(acc, v) if self.respond_to? acc
|
17
|
+
end
|
18
|
+
|
19
|
+
# Set some sane default values on a few options
|
20
|
+
self.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
21
|
+
self.single_logout_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
22
|
+
# Default cache TTL for metadata is 1 day
|
23
|
+
self.idp_metadata_ttl = 86400
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'federa/ruby-saml/logging'
|
2
|
+
require 'federa/ruby-saml/coding'
|
3
|
+
require 'federa/ruby-saml/request'
|
4
|
+
require 'federa/ruby-saml/authrequest'
|
5
|
+
require 'federa/ruby-saml/logout_request'
|
6
|
+
require 'federa/ruby-saml/logout_response'
|
7
|
+
require 'federa/ruby-saml/response'
|
8
|
+
require 'federa/ruby-saml/settings'
|
9
|
+
require 'federa/ruby-saml/validation_error'
|
10
|
+
require 'federa/ruby-saml/metadata'
|
11
|
+
require 'federa/ruby-saml/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>
|