ruby-saml 0.5.3 → 0.6.0
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.
Potentially problematic release.
This version of ruby-saml might be problematic. Click here for more details.
- data/.gitignore +5 -0
- data/.travis.yml +5 -0
- data/Gemfile +10 -6
- data/{README.rdoc → README.md} +31 -26
- data/lib/onelogin/ruby-saml/authrequest.rb +23 -18
- data/lib/onelogin/ruby-saml/logging.rb +4 -0
- data/lib/onelogin/ruby-saml/logoutrequest.rb +80 -0
- data/lib/onelogin/ruby-saml/response.rb +38 -4
- data/lib/onelogin/ruby-saml/settings.rb +10 -1
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/ruby-saml.rb +1 -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 +52 -36
- data/ruby-saml.gemspec +4 -26
- data/test/logoutrequest_test.rb +98 -0
- data/test/response_test.rb +40 -2
- data/test/responses/adfs_response_sha1.xml +46 -0
- data/test/responses/{adfs_response.xml → adfs_response_sha256.xml} +0 -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/settings_test.rb +22 -2
- data/test/test_helper.rb +2 -0
- data/test/xml_security_test.rb +103 -4
- metadata +79 -105
- data/Gemfile.lock +0 -38
data/lib/xml_security.rb
CHANGED
@@ -26,7 +26,7 @@ require 'rubygems'
|
|
26
26
|
require "rexml/document"
|
27
27
|
require "rexml/xpath"
|
28
28
|
require "openssl"
|
29
|
-
require
|
29
|
+
require 'nokogiri'
|
30
30
|
require "digest/sha1"
|
31
31
|
require "digest/sha2"
|
32
32
|
require "onelogin/ruby-saml/validation_error"
|
@@ -34,9 +34,10 @@ require "onelogin/ruby-saml/validation_error"
|
|
34
34
|
module XMLSecurity
|
35
35
|
|
36
36
|
class SignedDocument < REXML::Document
|
37
|
+
C14N = "http://www.w3.org/2001/10/xml-exc-c14n#"
|
37
38
|
DSIG = "http://www.w3.org/2000/09/xmldsig#"
|
38
39
|
|
39
|
-
attr_accessor :signed_element_id
|
40
|
+
attr_accessor :signed_element_id, :sig_element, :noko_sig_element
|
40
41
|
|
41
42
|
def initialize(response)
|
42
43
|
super(response)
|
@@ -45,9 +46,10 @@ module XMLSecurity
|
|
45
46
|
|
46
47
|
def validate(idp_cert_fingerprint, soft = true)
|
47
48
|
# get cert from response
|
48
|
-
|
49
|
-
|
50
|
-
|
49
|
+
cert_element = REXML::XPath.first(self, "//ds:X509Certificate", { "ds"=>DSIG })
|
50
|
+
base64_cert = cert_element.text
|
51
|
+
cert_text = Base64.decode64(base64_cert)
|
52
|
+
cert = OpenSSL::X509::Certificate.new(cert_text)
|
51
53
|
|
52
54
|
# check cert matches registered idp cert
|
53
55
|
fingerprint = Digest::SHA1.hexdigest(cert.to_der)
|
@@ -63,40 +65,43 @@ module XMLSecurity
|
|
63
65
|
# validate references
|
64
66
|
|
65
67
|
# check for inclusive namespaces
|
68
|
+
inclusive_namespaces = extract_inclusive_namespaces
|
66
69
|
|
67
|
-
|
68
|
-
inclusive_namespace_element = REXML::XPath.first(self, "//ec:InclusiveNamespaces")
|
70
|
+
document = Nokogiri.parse(self.to_s)
|
69
71
|
|
70
|
-
|
71
|
-
|
72
|
-
|
72
|
+
# store and remove signature node
|
73
|
+
self.sig_element ||= begin
|
74
|
+
element = REXML::XPath.first(self, "//ds:Signature", {"ds"=>DSIG})
|
75
|
+
element.remove
|
73
76
|
end
|
74
77
|
|
75
|
-
|
76
|
-
|
77
|
-
sig_element
|
78
|
+
|
79
|
+
# verify signature
|
80
|
+
signed_info_element = REXML::XPath.first(sig_element, "//ds:SignedInfo", {"ds"=>DSIG})
|
81
|
+
self.noko_sig_element ||= document.at_xpath('//ds:Signature', 'ds' => DSIG)
|
82
|
+
noko_signed_info_element = noko_sig_element.at_xpath('./ds:SignedInfo', 'ds' => DSIG)
|
83
|
+
canon_algorithm = canon_algorithm REXML::XPath.first(sig_element, '//ds:CanonicalizationMethod')
|
84
|
+
canon_string = noko_signed_info_element.canonicalize(canon_algorithm)
|
85
|
+
noko_sig_element.remove
|
78
86
|
|
79
87
|
# check digests
|
80
88
|
REXML::XPath.each(sig_element, "//ds:Reference", {"ds"=>DSIG}) do |ref|
|
81
89
|
uri = ref.attributes.get_attribute("URI").value
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
canon_hashed_element =
|
86
|
-
|
87
|
-
|
88
|
-
|
90
|
+
|
91
|
+
hashed_element = document.at_xpath("//*[@ID='#{uri[1..-1]}']")
|
92
|
+
canon_algorithm = canon_algorithm REXML::XPath.first(ref, '//ds:CanonicalizationMethod')
|
93
|
+
canon_hashed_element = hashed_element.canonicalize(canon_algorithm, inclusive_namespaces).gsub('&','&')
|
94
|
+
|
95
|
+
digest_algorithm = algorithm(REXML::XPath.first(ref, "//ds:DigestMethod"))
|
96
|
+
|
97
|
+
hash = digest_algorithm.digest(canon_hashed_element)
|
98
|
+
digest_value = Base64.decode64(REXML::XPath.first(ref, "//ds:DigestValue", {"ds"=>DSIG}).text)
|
89
99
|
|
90
100
|
unless digests_match?(hash, digest_value)
|
91
101
|
return soft ? false : (raise Onelogin::Saml::ValidationError.new("Digest mismatch"))
|
92
102
|
end
|
93
103
|
end
|
94
104
|
|
95
|
-
# verify signature
|
96
|
-
canoner = XML::Util::XmlCanonicalizer.new(false, true)
|
97
|
-
signed_info_element = REXML::XPath.first(sig_element, "//ds:SignedInfo", {"ds"=>DSIG})
|
98
|
-
canon_string = canoner.canonicalize(signed_info_element)
|
99
|
-
|
100
105
|
base64_signature = REXML::XPath.first(sig_element, "//ds:SignatureValue", {"ds"=>DSIG}).text
|
101
106
|
signature = Base64.decode64(base64_signature)
|
102
107
|
|
@@ -105,10 +110,10 @@ module XMLSecurity
|
|
105
110
|
cert = OpenSSL::X509::Certificate.new(cert_text)
|
106
111
|
|
107
112
|
# signature method
|
108
|
-
|
113
|
+
signature_algorithm = algorithm(REXML::XPath.first(signed_info_element, "//ds:SignatureMethod", {"ds"=>DSIG}))
|
109
114
|
|
110
|
-
|
111
|
-
return soft ? false : (raise ValidationError.new("Key validation error"))
|
115
|
+
unless cert.public_key.verify(signature_algorithm.new, signature, canon_string)
|
116
|
+
return soft ? false : (raise Onelogin::Saml::ValidationError.new("Key validation error"))
|
112
117
|
end
|
113
118
|
|
114
119
|
return true
|
@@ -125,17 +130,19 @@ module XMLSecurity
|
|
125
130
|
self.signed_element_id = reference_element.attribute("URI").value[1..-1] unless reference_element.nil?
|
126
131
|
end
|
127
132
|
|
128
|
-
def
|
129
|
-
algorithm = element.attribute(
|
130
|
-
|
133
|
+
def canon_algorithm(element)
|
134
|
+
algorithm = element.attribute('Algorithm').value if element
|
135
|
+
case algorithm
|
136
|
+
when "http://www.w3.org/2001/10/xml-exc-c14n#" then Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
|
137
|
+
when "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" then Nokogiri::XML::XML_C14N_1_0
|
138
|
+
when "http://www.w3.org/2006/12/xml-c14n11" then Nokogiri::XML::XML_C14N_1_1
|
139
|
+
else Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
|
140
|
+
end
|
131
141
|
end
|
132
142
|
|
133
|
-
def
|
143
|
+
def algorithm(element)
|
134
144
|
algorithm = element.attribute("Algorithm").value if element
|
135
|
-
|
136
|
-
algorithm =~ /sha(.*?)$/i
|
137
|
-
algorithm = $1.to_i
|
138
|
-
end
|
145
|
+
algorithm = algorithm && algorithm =~ /sha(.*?)$/i && $1.to_i
|
139
146
|
case algorithm
|
140
147
|
when 256 then OpenSSL::Digest::SHA256
|
141
148
|
when 384 then OpenSSL::Digest::SHA384
|
@@ -145,5 +152,14 @@ module XMLSecurity
|
|
145
152
|
end
|
146
153
|
end
|
147
154
|
|
155
|
+
def extract_inclusive_namespaces
|
156
|
+
if element = REXML::XPath.first(self, "//ec:InclusiveNamespaces", { "ec" => C14N })
|
157
|
+
prefix_list = element.attributes.get_attribute("PrefixList").value
|
158
|
+
prefix_list.split(" ")
|
159
|
+
else
|
160
|
+
[]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
148
164
|
end
|
149
165
|
end
|
data/ruby-saml.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.email = %q{support@onelogin.com}
|
13
13
|
s.extra_rdoc_files = [
|
14
14
|
"LICENSE",
|
15
|
-
"README.
|
15
|
+
"README.md"
|
16
16
|
]
|
17
17
|
s.files = `git ls-files`.split("\n")
|
18
18
|
s.homepage = %q{http://github.com/onelogin/ruby-saml}
|
@@ -23,29 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.summary = %q{SAML Ruby Tookit}
|
24
24
|
s.test_files = `git ls-files test/*`.split("\n")
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
31
|
-
s.add_runtime_dependency(%q<canonix>, ["~> 0.1"])
|
32
|
-
s.add_runtime_dependency(%q<uuid>, ["~> 2.3"])
|
33
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
34
|
-
s.add_development_dependency(%q<ruby-debug>, [">= 0"])
|
35
|
-
s.add_development_dependency(%q<mocha>, [">= 0"])
|
36
|
-
else
|
37
|
-
s.add_dependency(%q<canonix>, ["~> 0.1"])
|
38
|
-
s.add_dependency(%q<uuid>, ["~> 2.3"])
|
39
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
40
|
-
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
41
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
42
|
-
end
|
43
|
-
else
|
44
|
-
s.add_dependency(%q<canonix>, ["~> 0.1"])
|
45
|
-
s.add_dependency(%q<uuid>, ["~> 2.3"])
|
46
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
47
|
-
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
48
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
49
|
-
end
|
26
|
+
s.add_runtime_dependency("canonix", ["0.1.1"])
|
27
|
+
s.add_runtime_dependency("uuid", ["~> 2.3"])
|
28
|
+
s.add_runtime_dependency("nokogiri")
|
50
29
|
end
|
51
|
-
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
|
+
|
3
|
+
class RequestTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "Logoutrequest" do
|
6
|
+
settings = Onelogin::Saml::Settings.new
|
7
|
+
|
8
|
+
should "create the deflated SAMLRequest URL parameter" do
|
9
|
+
settings.idp_slo_target_url = "http://unauth.com/logout"
|
10
|
+
unauth_url = Onelogin::Saml::Logoutrequest.new.create(settings)
|
11
|
+
assert unauth_url =~ /^http:\/\/unauth\.com\/logout\?SAMLRequest=/
|
12
|
+
|
13
|
+
inflated = decode_saml_request_payload(unauth_url)
|
14
|
+
|
15
|
+
assert_match /^<samlp:LogoutRequest/, inflated
|
16
|
+
end
|
17
|
+
|
18
|
+
should "support additional params" do
|
19
|
+
|
20
|
+
unauth_url = Onelogin::Saml::Logoutrequest.new.create(settings, { :hello => nil })
|
21
|
+
assert unauth_url =~ /&hello=$/
|
22
|
+
|
23
|
+
unauth_url = Onelogin::Saml::Logoutrequest.new.create(settings, { :foo => "bar" })
|
24
|
+
assert unauth_url =~ /&foo=bar$/
|
25
|
+
end
|
26
|
+
|
27
|
+
should "set sessionindex" do
|
28
|
+
settings.idp_slo_target_url = "http://example.com"
|
29
|
+
sessionidx = UUID.new.generate
|
30
|
+
settings.sessionindex = sessionidx
|
31
|
+
|
32
|
+
unauth_url = Onelogin::Saml::Logoutrequest.new.create(settings, { :name_id => "there" })
|
33
|
+
inflated = decode_saml_request_payload(unauth_url)
|
34
|
+
|
35
|
+
assert_match /<samlp:SessionIndex/, inflated
|
36
|
+
assert_match %r(#{sessionidx}</samlp:SessionIndex>), inflated
|
37
|
+
end
|
38
|
+
|
39
|
+
should "set name_identifier_value" do
|
40
|
+
settings = Onelogin::Saml::Settings.new
|
41
|
+
settings.idp_slo_target_url = "http://example.com"
|
42
|
+
settings.name_identifier_format = "transient"
|
43
|
+
name_identifier_value = "abc123"
|
44
|
+
settings.name_identifier_value = name_identifier_value
|
45
|
+
|
46
|
+
unauth_url = Onelogin::Saml::Logoutrequest.new.create(settings, { :name_id => "there" })
|
47
|
+
inflated = decode_saml_request_payload(unauth_url)
|
48
|
+
|
49
|
+
assert_match /<saml:NameID/, inflated
|
50
|
+
assert_match %r(#{name_identifier_value}</saml:NameID>), inflated
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when the target url doesn't contain a query string" do
|
54
|
+
should "create the SAMLRequest parameter correctly" do
|
55
|
+
settings = Onelogin::Saml::Settings.new
|
56
|
+
settings.idp_slo_target_url = "http://example.com"
|
57
|
+
|
58
|
+
unauth_url = Onelogin::Saml::Logoutrequest.new.create(settings)
|
59
|
+
assert unauth_url =~ /^http:\/\/example.com\?SAMLRequest/
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when the target url contains a query string" do
|
64
|
+
should "create the SAMLRequest parameter correctly" do
|
65
|
+
settings = Onelogin::Saml::Settings.new
|
66
|
+
settings.idp_slo_target_url = "http://example.com?field=value"
|
67
|
+
|
68
|
+
unauth_url = Onelogin::Saml::Logoutrequest.new.create(settings)
|
69
|
+
assert unauth_url =~ /^http:\/\/example.com\?field=value&SAMLRequest/
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "consumation of logout may need to track the transaction" do
|
74
|
+
should "have access to the request uuid" do
|
75
|
+
settings = Onelogin::Saml::Settings.new
|
76
|
+
settings.idp_slo_target_url = "http://example.com?field=value"
|
77
|
+
|
78
|
+
unauth_req = Onelogin::Saml::Logoutrequest.new
|
79
|
+
unauth_url = unauth_req.create(settings)
|
80
|
+
|
81
|
+
inflated = decode_saml_request_payload(unauth_url)
|
82
|
+
assert_match %r[ID='#{unauth_req.uuid}'], inflated
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def decode_saml_request_payload(unauth_url)
|
88
|
+
payload = CGI.unescape(unauth_url.split("SAMLRequest=").last)
|
89
|
+
decoded = Base64.decode64(payload)
|
90
|
+
|
91
|
+
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
92
|
+
inflated = zstream.inflate(decoded)
|
93
|
+
zstream.finish
|
94
|
+
zstream.close
|
95
|
+
inflated
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
data/test/response_test.rb
CHANGED
@@ -27,6 +27,12 @@ class RubySamlTest < Test::Unit::TestCase
|
|
27
27
|
assert !response.name_id.nil?
|
28
28
|
end
|
29
29
|
|
30
|
+
should "default to raw input when a response is not Base64 encoded" do
|
31
|
+
decoded = Base64.decode64(response_document_2)
|
32
|
+
response = Onelogin::Saml::Response.new(decoded)
|
33
|
+
assert response.document
|
34
|
+
end
|
35
|
+
|
30
36
|
context "Assertion" do
|
31
37
|
should "only retreive an assertion with an ID that matches the signature's reference URI" do
|
32
38
|
response = Onelogin::Saml::Response.new(wrapped_response_2)
|
@@ -89,14 +95,34 @@ class RubySamlTest < Test::Unit::TestCase
|
|
89
95
|
assert response.name_id == "test@onelogin.com"
|
90
96
|
end
|
91
97
|
|
98
|
+
should "support dynamic namespace resolution on signature elements" do
|
99
|
+
response = Onelogin::Saml::Response.new(fixture("no_signature_ns.xml"))
|
100
|
+
response.stubs(:conditions).returns(nil)
|
101
|
+
settings = Onelogin::Saml::Settings.new
|
102
|
+
response.settings = settings
|
103
|
+
settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
|
104
|
+
XMLSecurity::SignedDocument.any_instance.expects(:validate_doc).returns(true)
|
105
|
+
assert response.validate!
|
106
|
+
end
|
107
|
+
|
92
108
|
should "validate ADFS assertions" do
|
93
|
-
response = Onelogin::Saml::Response.new(fixture(:
|
109
|
+
response = Onelogin::Saml::Response.new(fixture(:adfs_response_sha256))
|
94
110
|
response.stubs(:conditions).returns(nil)
|
95
111
|
settings = Onelogin::Saml::Settings.new
|
96
112
|
settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
|
97
113
|
response.settings = settings
|
98
114
|
assert response.validate!
|
99
115
|
end
|
116
|
+
|
117
|
+
should "validate SAML 2.0 XML structure" do
|
118
|
+
resp_xml = Base64.decode64(response_document_4).gsub(/emailAddress/,'test')
|
119
|
+
response = Onelogin::Saml::Response.new(Base64.encode64(resp_xml))
|
120
|
+
response.stubs(:conditions).returns(nil)
|
121
|
+
settings = Onelogin::Saml::Settings.new
|
122
|
+
settings.idp_cert_fingerprint = signature_fingerprint_1
|
123
|
+
response.settings = settings
|
124
|
+
assert_raises(Onelogin::Saml::ValidationError, 'Digest mismatch'){ response.validate! }
|
125
|
+
end
|
100
126
|
end
|
101
127
|
|
102
128
|
context "#name_id" do
|
@@ -171,11 +197,23 @@ class RubySamlTest < Test::Unit::TestCase
|
|
171
197
|
end
|
172
198
|
|
173
199
|
context "#issuer" do
|
174
|
-
should "return the issuer
|
200
|
+
should "return the issuer inside the response assertion" do
|
201
|
+
response = Onelogin::Saml::Response.new(response_document)
|
202
|
+
assert_equal "https://app.onelogin.com/saml/metadata/13590", response.issuer
|
203
|
+
end
|
204
|
+
|
205
|
+
should "return the issuer inside the response" do
|
175
206
|
response = Onelogin::Saml::Response.new(response_document_2)
|
176
207
|
assert_equal "wibble", response.issuer
|
177
208
|
end
|
178
209
|
end
|
210
|
+
|
211
|
+
context "#success" do
|
212
|
+
should "find a status code that says success" do
|
213
|
+
response = Onelogin::Saml::Response.new(response_document)
|
214
|
+
response.success?
|
215
|
+
end
|
216
|
+
end
|
179
217
|
|
180
218
|
end
|
181
219
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_0263a07b-205f-479c-90fc-7495715ecbbf" Version="2.0" IssueInstant="2011-06-22T12:49:30.348Z" Destination="https://someone.example.com/endpoint" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="_fc4a34b0-7efb-012e-caae-782bcb13bb38">
|
3
|
+
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">http://login.example.com/issuer</Issuer>
|
4
|
+
<samlp:Status>
|
5
|
+
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
|
6
|
+
</samlp:Status>
|
7
|
+
<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_721b4a5a-d7e1-4861-9754-a9b197b6f9ab" IssueInstant="2011-06-22T12:49:30.348Z" Version="2.0">
|
8
|
+
<Issuer>http://login.example.com/issuer</Issuer>
|
9
|
+
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
10
|
+
<ds:SignedInfo>
|
11
|
+
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
12
|
+
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha1"/>
|
13
|
+
<ds:Reference URI="#_721b4a5a-d7e1-4861-9754-a9b197b6f9ab">
|
14
|
+
<ds:Transforms>
|
15
|
+
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
16
|
+
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
17
|
+
</ds:Transforms>
|
18
|
+
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha1"/>
|
19
|
+
<ds:DigestValue>tGpkynNC34A5SFqDSfXmPSiIGpU=</ds:DigestValue>
|
20
|
+
</ds:Reference>
|
21
|
+
</ds:SignedInfo>
|
22
|
+
<ds:SignatureValue>WXtmslqh2npLtwhvU8yVx0pvH7E1s8ASksv7VtWirQDFrRRO9k+sNnQcGzA75QNyd6nP+T2e+ofIWyj8G70Rd6gEU4ZmV1vlGVq49Ilc7r/oxauitIuasOvrmpyHCXRbttYeWz4T5xoTCDx9RZQvI4fdrFugrymFT2OREFx1lSk=</ds:SignatureValue>
|
23
|
+
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
24
|
+
<ds:X509Data>
|
25
|
+
<ds:X509Certificate>LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURxekNDQXhTZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBRENCaGpFTE1Ba0dBMVVFQmhNQ1FWVXgKRERBS0JnTlZCQWdUQTA1VFZ6RVBNQTBHQTFVRUJ4TUdVM2xrYm1WNU1Rd3dDZ1lEVlFRS0RBTlFTVlF4Q1RBSApCZ05WQkFzTUFERVlNQllHQTFVRUF3d1BiR0YzY21WdVkyVndhWFF1WTI5dE1TVXdJd1lKS29aSWh2Y05BUWtCCkRCWnNZWGR5Wlc1alpTNXdhWFJBWjIxaGFXd3VZMjl0TUI0WERURXlNRFF4T1RJeU5UUXhPRm9YRFRNeU1EUXgKTkRJeU5UUXhPRm93Z1lZeEN6QUpCZ05WQkFZVEFrRlZNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVApCbE41Wkc1bGVURU1NQW9HQTFVRUNnd0RVRWxVTVFrd0J3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psCmJtTmxjR2wwTG1OdmJURWxNQ01HQ1NxR1NJYjNEUUVKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnYKYlRDQm56QU5CZ2txaGtpRzl3MEJBUUVGQUFPQmpRQXdnWWtDZ1lFQXFqaWUzUjJvaStwRGFldndJeXMvbWJVVApubkdsa3h0ZGlrcnExMXZleHd4SmlQTmhtaHFSVzNtVXVKRXpsbElkVkw2RW14R1lUcXBxZjkzSGxoa3NhZUowCjhVZ2pQOVVtTVlyaFZKdTFqY0ZXVjdmei9yKzIxL2F3VG5EVjlzTVlRcXVJUllZeTdiRzByMU9iaXdkb3ZudGsKN2dGSTA2WjB2WmFjREU1Ym9xVUNBd0VBQWFPQ0FTVXdnZ0VoTUFrR0ExVWRFd1FDTUFBd0N3WURWUjBQQkFRRApBZ1VnTUIwR0ExVWREZ1FXQkJTUk9OOEdKOG8rOGpnRnRqa3R3WmRxeDZCUnlUQVRCZ05WSFNVRUREQUtCZ2dyCkJnRUZCUWNEQVRBZEJnbGdoa2dCaHZoQ0FRMEVFQllPVkdWemRDQllOVEE1SUdObGNuUXdnYk1HQTFVZEl3U0IKcXpDQnFJQVVrVGpmQmlmS1B2STRCYlk1TGNHWGFzZWdVY21oZ1l5a2dZa3dnWVl4Q3pBSkJnTlZCQVlUQWtGVgpNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVEJsTjVaRzVsZVRFTU1Bb0dBMVVFQ2d3RFVFbFVNUWt3CkJ3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psYm1ObGNHbDBMbU52YlRFbE1DTUdDU3FHU0liM0RRRUoKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnZiWUlCQVRBTkJna3Foa2lHOXcwQkFRc0ZBQU9CZ1FDRQpUQWVKVERTQVc2ejFVRlRWN1FyZWg0VUxGT1JhajkrZUN1RjNLV0RIYyswSVFDajlyZG5ERzRRL3dmNy9yYVEwCkpuUFFDU0NkclBMSmV5b1BIN1FhVHdvYUY3ZHpWdzRMQ3N5TkpURld4NGNNNTBWdzZSNWZET2dpQzhic2ZmUzgKQkptb3VscnJaRE5OVmpHOG1XNmNMeHJZdlZRT3JSVmVjQ0ZJZ3NzQ2JBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=</ds:X509Certificate>
|
26
|
+
</ds:X509Data>
|
27
|
+
</KeyInfo>
|
28
|
+
</ds:Signature>
|
29
|
+
<Subject>
|
30
|
+
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">hello@example.com</NameID>
|
31
|
+
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
|
32
|
+
<SubjectConfirmationData InResponseTo="_fc4a34b0-7efb-012e-caae-782bcb13bb38" NotOnOrAfter="2011-06-22T12:54:30.348Z" Recipient="https://someone.example.com/endpoint"/>
|
33
|
+
</SubjectConfirmation>
|
34
|
+
</Subject>
|
35
|
+
<Conditions NotBefore="2011-06-22T12:49:30.332Z" NotOnOrAfter="2011-06-22T13:49:30.332Z">
|
36
|
+
<AudienceRestriction>
|
37
|
+
<Audience>example.com</Audience>
|
38
|
+
</AudienceRestriction>
|
39
|
+
</Conditions>
|
40
|
+
<AuthnStatement AuthnInstant="2011-06-22T12:49:30.112Z" SessionIndex="_721b4a5a-d7e1-4861-9754-a9b197b6f9ab">
|
41
|
+
<AuthnContext>
|
42
|
+
<AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</AuthnContextClassRef>
|
43
|
+
</AuthnContext>
|
44
|
+
</AuthnStatement>
|
45
|
+
</Assertion>
|
46
|
+
</samlp:Response>
|
File without changes
|
@@ -0,0 +1,46 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_0263a07b-205f-479c-90fc-7495715ecbbf" Version="2.0" IssueInstant="2011-06-22T12:49:30.348Z" Destination="https://someone.example.com/endpoint" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="_fc4a34b0-7efb-012e-caae-782bcb13bb38">
|
3
|
+
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">http://login.example.com/issuer</Issuer>
|
4
|
+
<samlp:Status>
|
5
|
+
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
|
6
|
+
</samlp:Status>
|
7
|
+
<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_721b4a5a-d7e1-4861-9754-a9b197b6f9ab" IssueInstant="2011-06-22T12:49:30.348Z" Version="2.0">
|
8
|
+
<Issuer>http://login.example.com/issuer</Issuer>
|
9
|
+
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
10
|
+
<ds:SignedInfo>
|
11
|
+
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
12
|
+
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"/>
|
13
|
+
<ds:Reference URI="#_721b4a5a-d7e1-4861-9754-a9b197b6f9ab">
|
14
|
+
<ds:Transforms>
|
15
|
+
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
16
|
+
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
17
|
+
</ds:Transforms>
|
18
|
+
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha384"/>
|
19
|
+
<ds:DigestValue>XU0mb78TVA+VwcA71jxe5osjiOzOP/OwDcJ8t/mn2d9+/V2zxejEo9+fkSY2ZR0Z</ds:DigestValue>
|
20
|
+
</ds:Reference>
|
21
|
+
</ds:SignedInfo>
|
22
|
+
<ds:SignatureValue>bq1zDllmAFzx0O3HAAoedSqQIl/n2+mK2Vx1pK0/yEpuc84ovwmau/ZfHk3MFNQjuxL+JmlO7I3c6CEmOGeAupFTpnFGkRfJGSu6ilvcL4yasPq80LNEcCYhApiEW2pJXs5t3sfOdG2MJHTuMvz4MtnrLd9Cuf/EQK2a27HDrB4=</ds:SignatureValue>
|
23
|
+
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
24
|
+
<ds:X509Data>
|
25
|
+
<ds:X509Certificate>LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURxekNDQXhTZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBRENCaGpFTE1Ba0dBMVVFQmhNQ1FWVXgKRERBS0JnTlZCQWdUQTA1VFZ6RVBNQTBHQTFVRUJ4TUdVM2xrYm1WNU1Rd3dDZ1lEVlFRS0RBTlFTVlF4Q1RBSApCZ05WQkFzTUFERVlNQllHQTFVRUF3d1BiR0YzY21WdVkyVndhWFF1WTI5dE1TVXdJd1lKS29aSWh2Y05BUWtCCkRCWnNZWGR5Wlc1alpTNXdhWFJBWjIxaGFXd3VZMjl0TUI0WERURXlNRFF4T1RJeU5UUXhPRm9YRFRNeU1EUXgKTkRJeU5UUXhPRm93Z1lZeEN6QUpCZ05WQkFZVEFrRlZNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVApCbE41Wkc1bGVURU1NQW9HQTFVRUNnd0RVRWxVTVFrd0J3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psCmJtTmxjR2wwTG1OdmJURWxNQ01HQ1NxR1NJYjNEUUVKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnYKYlRDQm56QU5CZ2txaGtpRzl3MEJBUUVGQUFPQmpRQXdnWWtDZ1lFQXFqaWUzUjJvaStwRGFldndJeXMvbWJVVApubkdsa3h0ZGlrcnExMXZleHd4SmlQTmhtaHFSVzNtVXVKRXpsbElkVkw2RW14R1lUcXBxZjkzSGxoa3NhZUowCjhVZ2pQOVVtTVlyaFZKdTFqY0ZXVjdmei9yKzIxL2F3VG5EVjlzTVlRcXVJUllZeTdiRzByMU9iaXdkb3ZudGsKN2dGSTA2WjB2WmFjREU1Ym9xVUNBd0VBQWFPQ0FTVXdnZ0VoTUFrR0ExVWRFd1FDTUFBd0N3WURWUjBQQkFRRApBZ1VnTUIwR0ExVWREZ1FXQkJTUk9OOEdKOG8rOGpnRnRqa3R3WmRxeDZCUnlUQVRCZ05WSFNVRUREQUtCZ2dyCkJnRUZCUWNEQVRBZEJnbGdoa2dCaHZoQ0FRMEVFQllPVkdWemRDQllOVEE1SUdObGNuUXdnYk1HQTFVZEl3U0IKcXpDQnFJQVVrVGpmQmlmS1B2STRCYlk1TGNHWGFzZWdVY21oZ1l5a2dZa3dnWVl4Q3pBSkJnTlZCQVlUQWtGVgpNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVEJsTjVaRzVsZVRFTU1Bb0dBMVVFQ2d3RFVFbFVNUWt3CkJ3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psYm1ObGNHbDBMbU52YlRFbE1DTUdDU3FHU0liM0RRRUoKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnZiWUlCQVRBTkJna3Foa2lHOXcwQkFRc0ZBQU9CZ1FDRQpUQWVKVERTQVc2ejFVRlRWN1FyZWg0VUxGT1JhajkrZUN1RjNLV0RIYyswSVFDajlyZG5ERzRRL3dmNy9yYVEwCkpuUFFDU0NkclBMSmV5b1BIN1FhVHdvYUY3ZHpWdzRMQ3N5TkpURld4NGNNNTBWdzZSNWZET2dpQzhic2ZmUzgKQkptb3VscnJaRE5OVmpHOG1XNmNMeHJZdlZRT3JSVmVjQ0ZJZ3NzQ2JBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=</ds:X509Certificate>
|
26
|
+
</ds:X509Data>
|
27
|
+
</KeyInfo>
|
28
|
+
</ds:Signature>
|
29
|
+
<Subject>
|
30
|
+
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">hello@example.com</NameID>
|
31
|
+
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
|
32
|
+
<SubjectConfirmationData InResponseTo="_fc4a34b0-7efb-012e-caae-782bcb13bb38" NotOnOrAfter="2011-06-22T12:54:30.348Z" Recipient="https://someone.example.com/endpoint"/>
|
33
|
+
</SubjectConfirmation>
|
34
|
+
</Subject>
|
35
|
+
<Conditions NotBefore="2011-06-22T12:49:30.332Z" NotOnOrAfter="2011-06-22T13:49:30.332Z">
|
36
|
+
<AudienceRestriction>
|
37
|
+
<Audience>example.com</Audience>
|
38
|
+
</AudienceRestriction>
|
39
|
+
</Conditions>
|
40
|
+
<AuthnStatement AuthnInstant="2011-06-22T12:49:30.112Z" SessionIndex="_721b4a5a-d7e1-4861-9754-a9b197b6f9ab">
|
41
|
+
<AuthnContext>
|
42
|
+
<AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</AuthnContextClassRef>
|
43
|
+
</AuthnContext>
|
44
|
+
</AuthnStatement>
|
45
|
+
</Assertion>
|
46
|
+
</samlp:Response>
|