ruby-saml 0.4.5 → 0.4.6
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/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/onelogin/saml.rb +1 -0
- data/lib/onelogin/saml/response.rb +54 -19
- data/lib/onelogin/saml/validation_error.rb +7 -0
- data/lib/xml_security.rb +35 -21
- data/ruby-saml.gemspec +15 -4
- data/test/request_test.rb +33 -0
- data/test/{ruby-saml_test.rb → response_test.rb} +34 -56
- data/test/responses/adfs_response.xml.base64 +91 -0
- data/test/responses/open_saml_response.xml +56 -0
- data/test/responses/simple_saml_php.xml +71 -0
- data/test/settings_test.rb +23 -0
- data/test/test_helper.rb +10 -0
- data/test/xml_security_test.rb +1 -1
- metadata +29 -7
data/Rakefile
CHANGED
@@ -13,6 +13,7 @@ begin
|
|
13
13
|
gem.add_dependency("canonix","~> 0.1")
|
14
14
|
gem.add_dependency("uuid","~> 2.3")
|
15
15
|
gem.add_development_dependency "shoulda"
|
16
|
+
gem.add_development_dependency "ruby-debug"
|
16
17
|
gem.add_development_dependency "mocha"
|
17
18
|
#gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
19
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.6
|
data/lib/onelogin/saml.rb
CHANGED
@@ -2,48 +2,38 @@ require "xml_security"
|
|
2
2
|
require "time"
|
3
3
|
|
4
4
|
module Onelogin::Saml
|
5
|
+
|
5
6
|
class Response
|
6
7
|
ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
|
7
8
|
PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
|
8
9
|
DSIG = "http://www.w3.org/2000/09/xmldsig#"
|
9
10
|
|
10
|
-
attr_accessor :
|
11
|
+
attr_accessor :options, :response, :document, :settings
|
11
12
|
|
12
|
-
def initialize(response)
|
13
|
+
def initialize(response, options = {})
|
13
14
|
raise ArgumentError.new("Response cannot be nil") if response.nil?
|
15
|
+
self.options = options
|
14
16
|
self.response = response
|
15
17
|
self.document = XMLSecurity::SignedDocument.new(Base64.decode64(response))
|
16
18
|
end
|
17
19
|
|
18
20
|
def is_valid?
|
19
|
-
|
20
|
-
|
21
|
-
return false if settings.idp_cert_fingerprint.nil?
|
22
|
-
return false if !check_conditions
|
21
|
+
validate(soft = true)
|
22
|
+
end
|
23
23
|
|
24
|
-
|
24
|
+
def validate!
|
25
|
+
validate(soft = false)
|
25
26
|
end
|
26
27
|
|
27
28
|
# The value of the user identifier as designated by the initialization request response
|
28
29
|
def name_id
|
29
30
|
@name_id ||= begin
|
30
31
|
node = REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
|
32
|
+
node ||= REXML::XPath.first(document, "/p:Response[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Assertion/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
|
31
33
|
node.nil? ? nil : node.text
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
|
-
def check_conditions
|
36
|
-
return true if conditions.nil?
|
37
|
-
|
38
|
-
not_before = parse_time(conditions, "NotBefore")
|
39
|
-
return false if not_before && Time.now.utc < not_before
|
40
|
-
|
41
|
-
not_on_or_after = parse_time(conditions, "NotOnOrAfter")
|
42
|
-
return false if not_on_or_after && Time.now.utc >= not_on_or_after
|
43
|
-
|
44
|
-
true
|
45
|
-
end
|
46
|
-
|
47
37
|
# A hash of alle the attributes with the response. Assuming there is only one value for each key
|
48
38
|
def attributes
|
49
39
|
@attr_statements ||= begin
|
@@ -84,6 +74,51 @@ module Onelogin::Saml
|
|
84
74
|
|
85
75
|
private
|
86
76
|
|
77
|
+
def validation_error(message)
|
78
|
+
raise ValidationError.new(message)
|
79
|
+
end
|
80
|
+
|
81
|
+
def validate(soft = true)
|
82
|
+
validate_response_state(soft) &&
|
83
|
+
validate_conditions(soft) &&
|
84
|
+
document.validate(settings.idp_cert_fingerprint, soft)
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate_response_state(soft = true)
|
88
|
+
if response.empty?
|
89
|
+
return soft ? false : validation_error("Blank response")
|
90
|
+
end
|
91
|
+
|
92
|
+
if settings.nil?
|
93
|
+
return soft ? false : validation_error("No settings on response")
|
94
|
+
end
|
95
|
+
|
96
|
+
if settings.idp_cert_fingerprint.nil?
|
97
|
+
return soft ? false : validation_error("No fingerprint on settings")
|
98
|
+
end
|
99
|
+
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
def validate_conditions(soft = true)
|
104
|
+
return true if conditions.nil?
|
105
|
+
return true if options[:skip_conditions]
|
106
|
+
|
107
|
+
if not_before = parse_time(conditions, "NotBefore")
|
108
|
+
if Time.now.utc < not_before
|
109
|
+
return soft ? false : validation_error("Current time is earlier than NotBefore condition")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
if not_on_or_after = parse_time(conditions, "NotOnOrAfter")
|
114
|
+
if Time.now.utc >= not_on_or_after
|
115
|
+
return soft ? false : validation_error("Current time is on or after NotOnOrAfter condition")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
true
|
120
|
+
end
|
121
|
+
|
87
122
|
def parse_time(node, attribute)
|
88
123
|
if node && node.attributes[attribute]
|
89
124
|
Time.parse(node.attributes[attribute])
|
data/lib/xml_security.rb
CHANGED
@@ -28,11 +28,12 @@ require "rexml/xpath"
|
|
28
28
|
require "openssl"
|
29
29
|
require "xmlcanonicalizer"
|
30
30
|
require "digest/sha1"
|
31
|
+
require "onelogin/saml/validation_error"
|
31
32
|
|
32
33
|
module XMLSecurity
|
33
34
|
|
34
35
|
class SignedDocument < REXML::Document
|
35
|
-
DSIG
|
36
|
+
DSIG = "http://www.w3.org/2000/09/xmldsig#"
|
36
37
|
|
37
38
|
attr_accessor :signed_element_id
|
38
39
|
|
@@ -41,7 +42,7 @@ module XMLSecurity
|
|
41
42
|
extract_signed_element_id
|
42
43
|
end
|
43
44
|
|
44
|
-
def validate
|
45
|
+
def validate(idp_cert_fingerprint, soft = true)
|
45
46
|
# get cert from response
|
46
47
|
base64_cert = self.elements["//ds:X509Certificate"].text
|
47
48
|
cert_text = Base64.decode64(base64_cert)
|
@@ -49,33 +50,44 @@ module XMLSecurity
|
|
49
50
|
|
50
51
|
# check cert matches registered idp cert
|
51
52
|
fingerprint = Digest::SHA1.hexdigest(cert.to_der)
|
52
|
-
valid_flag = fingerprint == idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/,"").downcase
|
53
53
|
|
54
|
-
|
54
|
+
if fingerprint != idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/,"").downcase
|
55
|
+
return soft ? false : (raise Onelogin::Saml::ValidationError.new("Fingerprint mismatch"))
|
56
|
+
end
|
55
57
|
|
56
|
-
validate_doc(base64_cert,
|
58
|
+
validate_doc(base64_cert, soft)
|
57
59
|
end
|
58
60
|
|
59
|
-
def validate_doc(base64_cert,
|
61
|
+
def validate_doc(base64_cert, soft = true)
|
60
62
|
# validate references
|
63
|
+
|
64
|
+
# check for inclusive namespaces
|
65
|
+
|
66
|
+
inclusive_namespaces = []
|
67
|
+
inclusive_namespace_element = REXML::XPath.first(self, "//ec:InclusiveNamespaces")
|
68
|
+
|
69
|
+
if inclusive_namespace_element
|
70
|
+
prefix_list = inclusive_namespace_element.attributes.get_attribute('PrefixList').value
|
71
|
+
inclusive_namespaces = prefix_list.split(" ")
|
72
|
+
end
|
61
73
|
|
62
74
|
# remove signature node
|
63
75
|
sig_element = REXML::XPath.first(self, "//ds:Signature", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"})
|
64
76
|
sig_element.remove
|
65
77
|
|
66
|
-
#check digests
|
67
|
-
REXML::XPath.each(sig_element, "//ds:Reference", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}) do |
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
canoner
|
72
|
-
canon_hashed_element
|
73
|
-
hash
|
74
|
-
digest_value
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
78
|
+
# check digests
|
79
|
+
REXML::XPath.each(sig_element, "//ds:Reference", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}) do |ref|
|
80
|
+
uri = ref.attributes.get_attribute("URI").value
|
81
|
+
hashed_element = REXML::XPath.first(self, "//[@ID='#{uri[1,uri.size]}']")
|
82
|
+
canoner = XML::Util::XmlCanonicalizer.new(false, true)
|
83
|
+
canoner.inclusive_namespaces = inclusive_namespaces if canoner.respond_to?(:inclusive_namespaces) && !inclusive_namespaces.empty?
|
84
|
+
canon_hashed_element = canoner.canonicalize(hashed_element)
|
85
|
+
hash = Base64.encode64(Digest::SHA1.digest(canon_hashed_element)).chomp
|
86
|
+
digest_value = REXML::XPath.first(ref, "//ds:DigestValue", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}).text
|
87
|
+
|
88
|
+
if hash != digest_value
|
89
|
+
return soft ? false : (raise Onelogin::Saml::ValidationError.new("Digest mismatch"))
|
90
|
+
end
|
79
91
|
end
|
80
92
|
|
81
93
|
# verify signature
|
@@ -90,9 +102,11 @@ module XMLSecurity
|
|
90
102
|
cert_text = Base64.decode64(base64_cert)
|
91
103
|
cert = OpenSSL::X509::Certificate.new(cert_text)
|
92
104
|
|
93
|
-
|
105
|
+
if !cert.public_key.verify(OpenSSL::Digest::SHA1.new, signature, canon_string)
|
106
|
+
return soft ? false : (raise ValidationError.new("Key validation error"))
|
107
|
+
end
|
94
108
|
|
95
|
-
return
|
109
|
+
return true
|
96
110
|
end
|
97
111
|
|
98
112
|
private
|
data/ruby-saml.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ruby-saml}
|
8
|
-
s.version = "0.4.
|
8
|
+
s.version = "0.4.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["OneLogin LLC"]
|
12
|
-
s.date = %q{2011-06-
|
12
|
+
s.date = %q{2011-06-28}
|
13
13
|
s.description = %q{SAML toolkit for Ruby on Rails}
|
14
14
|
s.email = %q{support@onelogin.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -27,16 +27,22 @@ Gem::Specification.new do |s|
|
|
27
27
|
"lib/onelogin/saml/authrequest.rb",
|
28
28
|
"lib/onelogin/saml/response.rb",
|
29
29
|
"lib/onelogin/saml/settings.rb",
|
30
|
+
"lib/onelogin/saml/validation_error.rb",
|
30
31
|
"lib/ruby-saml.rb",
|
31
32
|
"lib/xml_security.rb",
|
32
33
|
"ruby-saml.gemspec",
|
34
|
+
"test/request_test.rb",
|
35
|
+
"test/response_test.rb",
|
36
|
+
"test/responses/adfs_response.xml.base64",
|
33
37
|
"test/responses/certificate1",
|
38
|
+
"test/responses/open_saml_response.xml",
|
34
39
|
"test/responses/response1.xml.base64",
|
35
40
|
"test/responses/response2.xml.base64",
|
36
41
|
"test/responses/response3.xml.base64",
|
37
42
|
"test/responses/response4.xml.base64",
|
38
43
|
"test/responses/response5.xml.base64",
|
39
|
-
"test/
|
44
|
+
"test/responses/simple_saml_php.xml",
|
45
|
+
"test/settings_test.rb",
|
40
46
|
"test/test_helper.rb",
|
41
47
|
"test/xml_security_test.rb"
|
42
48
|
]
|
@@ -46,7 +52,9 @@ Gem::Specification.new do |s|
|
|
46
52
|
s.rubygems_version = %q{1.3.7}
|
47
53
|
s.summary = %q{SAML Ruby Tookit}
|
48
54
|
s.test_files = [
|
49
|
-
"test/
|
55
|
+
"test/request_test.rb",
|
56
|
+
"test/response_test.rb",
|
57
|
+
"test/settings_test.rb",
|
50
58
|
"test/test_helper.rb",
|
51
59
|
"test/xml_security_test.rb"
|
52
60
|
]
|
@@ -59,17 +67,20 @@ Gem::Specification.new do |s|
|
|
59
67
|
s.add_runtime_dependency(%q<canonix>, ["~> 0.1"])
|
60
68
|
s.add_runtime_dependency(%q<uuid>, ["~> 2.3"])
|
61
69
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
70
|
+
s.add_development_dependency(%q<ruby-debug>, [">= 0"])
|
62
71
|
s.add_development_dependency(%q<mocha>, [">= 0"])
|
63
72
|
else
|
64
73
|
s.add_dependency(%q<canonix>, ["~> 0.1"])
|
65
74
|
s.add_dependency(%q<uuid>, ["~> 2.3"])
|
66
75
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
76
|
+
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
67
77
|
s.add_dependency(%q<mocha>, [">= 0"])
|
68
78
|
end
|
69
79
|
else
|
70
80
|
s.add_dependency(%q<canonix>, ["~> 0.1"])
|
71
81
|
s.add_dependency(%q<uuid>, ["~> 2.3"])
|
72
82
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
83
|
+
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
73
84
|
s.add_dependency(%q<mocha>, [">= 0"])
|
74
85
|
end
|
75
86
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
|
+
|
3
|
+
class RequestTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "Authrequest" do
|
6
|
+
should "create the deflated SAMLRequest URL parameter" do
|
7
|
+
settings = Onelogin::Saml::Settings.new
|
8
|
+
settings.idp_sso_target_url = "http://stuff.com"
|
9
|
+
auth_url = Onelogin::Saml::Authrequest.new.create(settings)
|
10
|
+
assert auth_url =~ /^http:\/\/stuff\.com\?SAMLRequest=/
|
11
|
+
payload = CGI.unescape(auth_url.split("=").last)
|
12
|
+
decoded = Base64.decode64(payload)
|
13
|
+
|
14
|
+
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
15
|
+
inflated = zstream.inflate(decoded)
|
16
|
+
zstream.finish
|
17
|
+
zstream.close
|
18
|
+
|
19
|
+
assert_match /^<samlp:AuthnRequest/, inflated
|
20
|
+
end
|
21
|
+
|
22
|
+
should "accept extra parameters" do
|
23
|
+
settings = Onelogin::Saml::Settings.new
|
24
|
+
settings.idp_sso_target_url = "http://stuff.com"
|
25
|
+
|
26
|
+
auth_url = Onelogin::Saml::Authrequest.new.create(settings, { :hello => "there" })
|
27
|
+
assert auth_url =~ /&hello=there$/
|
28
|
+
|
29
|
+
auth_url = Onelogin::Saml::Authrequest.new.create(settings, { :hello => nil })
|
30
|
+
assert auth_url =~ /&hello=$/
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -2,30 +2,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
|
2
2
|
|
3
3
|
class RubySamlTest < Test::Unit::TestCase
|
4
4
|
|
5
|
-
context "Settings" do
|
6
|
-
setup do
|
7
|
-
@settings = Onelogin::Saml::Settings.new
|
8
|
-
end
|
9
|
-
should "should provide getters and settings" do
|
10
|
-
accessors = [
|
11
|
-
:assertion_consumer_service_url, :issuer, :sp_name_qualifier, :sp_name_qualifier,
|
12
|
-
:idp_sso_target_url, :idp_cert_fingerprint, :name_identifier_format
|
13
|
-
]
|
14
|
-
|
15
|
-
accessors.each do |accessor|
|
16
|
-
value = Kernel.rand
|
17
|
-
@settings.send("#{accessor}=".to_sym, value)
|
18
|
-
assert_equal value, @settings.send(accessor)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
5
|
context "Response" do
|
24
|
-
should "provide setter for a logger" do
|
25
|
-
response = Onelogin::Saml::Response.new('')
|
26
|
-
assert response.logger = 'hello'
|
27
|
-
end
|
28
|
-
|
29
6
|
should "raise an exception when response is initialized with nil" do
|
30
7
|
assert_raises(ArgumentError) { Onelogin::Saml::Response.new(nil) }
|
31
8
|
end
|
@@ -39,6 +16,15 @@ class RubySamlTest < Test::Unit::TestCase
|
|
39
16
|
assert !response.name_id.nil?
|
40
17
|
end
|
41
18
|
|
19
|
+
context "#validate!" do
|
20
|
+
should "raise when encountering a condition that prevents the document from being valid" do
|
21
|
+
response = Onelogin::Saml::Response.new(response_document)
|
22
|
+
assert_raise(Onelogin::Saml::ValidationError) do
|
23
|
+
response.validate!
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
42
28
|
context "#is_valid?" do
|
43
29
|
should "return false when response is initialized with blank data" do
|
44
30
|
response = Onelogin::Saml::Response.new('')
|
@@ -52,7 +38,7 @@ class RubySamlTest < Test::Unit::TestCase
|
|
52
38
|
|
53
39
|
should "return true when the response is initialized with valid data" do
|
54
40
|
response = Onelogin::Saml::Response.new(response_document_4)
|
55
|
-
response.
|
41
|
+
response.stubs(:conditions).returns(nil)
|
56
42
|
assert !response.is_valid?
|
57
43
|
settings = Onelogin::Saml::Settings.new
|
58
44
|
assert !response.is_valid?
|
@@ -64,13 +50,22 @@ class RubySamlTest < Test::Unit::TestCase
|
|
64
50
|
|
65
51
|
should "not allow signature wrapping attack" do
|
66
52
|
response = Onelogin::Saml::Response.new(response_document_4)
|
67
|
-
response.
|
53
|
+
response.stubs(:conditions).returns(nil)
|
68
54
|
settings = Onelogin::Saml::Settings.new
|
69
55
|
settings.idp_cert_fingerprint = signature_fingerprint_1
|
70
56
|
response.settings = settings
|
71
57
|
assert response.is_valid?
|
72
58
|
assert response.name_id == "test@onelogin.com"
|
73
59
|
end
|
60
|
+
|
61
|
+
should_eventually "validate ADFS assertions" do
|
62
|
+
response = Onelogin::Saml::Response.new(fixture(:adfs_response))
|
63
|
+
response.stubs(:conditions).returns(nil)
|
64
|
+
settings = Onelogin::Saml::Settings.new
|
65
|
+
settings.idp_cert_fingerprint = "17:54:07:27:53:55:D1:93:67:A4:95:0A:6A:E4:D6:1E:FA:4A:94:1D"
|
66
|
+
response.settings = settings
|
67
|
+
assert response.validate!
|
68
|
+
end
|
74
69
|
end
|
75
70
|
|
76
71
|
context "#name_id" do
|
@@ -81,18 +76,28 @@ class RubySamlTest < Test::Unit::TestCase
|
|
81
76
|
response = Onelogin::Saml::Response.new(response_document_3)
|
82
77
|
assert_equal "someone@example.com", response.name_id
|
83
78
|
end
|
79
|
+
|
80
|
+
should_eventually "be extractable from an OpenSAML response" do
|
81
|
+
response = Onelogin::Saml::Response.new(fixture(:open_saml))
|
82
|
+
assert_equal "someone@example.org", response.name_id
|
83
|
+
end
|
84
|
+
|
85
|
+
should_eventually "be extractable from a Simple SAML PHP response" do
|
86
|
+
response = Onelogin::Saml::Response.new(fixture(:simple_saml_php))
|
87
|
+
assert_equal "someone@example.com", response.name_id
|
88
|
+
end
|
84
89
|
end
|
85
90
|
|
86
91
|
context "#check_conditions" do
|
87
92
|
should "check time conditions" do
|
88
93
|
response = Onelogin::Saml::Response.new(response_document)
|
89
|
-
assert !response.
|
94
|
+
assert !response.send(:validate_conditions, true)
|
90
95
|
response = Onelogin::Saml::Response.new(response_document_6)
|
91
|
-
assert response.
|
96
|
+
assert response.send(:validate_conditions, true)
|
92
97
|
time = Time.parse("2011-06-14T18:25:01.516Z")
|
93
98
|
Time.stubs(:now).returns(time)
|
94
99
|
response = Onelogin::Saml::Response.new(response_document_5)
|
95
|
-
assert response.
|
100
|
+
assert response.send(:validate_conditions, true)
|
96
101
|
end
|
97
102
|
end
|
98
103
|
|
@@ -133,34 +138,7 @@ class RubySamlTest < Test::Unit::TestCase
|
|
133
138
|
assert response.session_expires_at.nil?
|
134
139
|
end
|
135
140
|
end
|
136
|
-
end
|
137
|
-
|
138
|
-
context "Authrequest" do
|
139
|
-
should "create the deflated SAMLRequest URL parameter" do
|
140
|
-
settings = Onelogin::Saml::Settings.new
|
141
|
-
settings.idp_sso_target_url = "http://stuff.com"
|
142
|
-
auth_url = Onelogin::Saml::Authrequest.new.create(settings)
|
143
|
-
assert auth_url =~ /^http:\/\/stuff\.com\?SAMLRequest=/
|
144
|
-
payload = CGI.unescape(auth_url.split("=").last)
|
145
|
-
decoded = Base64.decode64(payload)
|
146
|
-
|
147
|
-
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
148
|
-
inflated = zstream.inflate(decoded)
|
149
|
-
zstream.finish
|
150
|
-
zstream.close
|
151
|
-
|
152
|
-
assert_match /^<samlp:AuthnRequest/, inflated
|
153
|
-
end
|
154
|
-
|
155
|
-
should "accept extra parameters" do
|
156
|
-
settings = Onelogin::Saml::Settings.new
|
157
|
-
settings.idp_sso_target_url = "http://stuff.com"
|
158
141
|
|
159
|
-
auth_url = Onelogin::Saml::Authrequest.new.create(settings, { :hello => "there" })
|
160
|
-
assert auth_url =~ /&hello=there$/
|
161
|
-
|
162
|
-
auth_url = Onelogin::Saml::Authrequest.new.create(settings, { :hello => nil })
|
163
|
-
assert auth_url =~ /&hello=$/
|
164
|
-
end
|
165
142
|
end
|
143
|
+
|
166
144
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzYW1scDpSZXNwb25zZSB4bWxuczpz
|
2
|
+
YW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJ
|
3
|
+
RD0iXzAyNjNhMDdiLTIwNWYtNDc5Yy05MGZjLTc0OTU3MTVlY2JiZiIgVmVy
|
4
|
+
c2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMjJUMTI6NDk6MzAu
|
5
|
+
MzQ4WiIgRGVzdGluYXRpb249Imh0dHBzOi8vc29tZW9uZS5leGFtcGxlLmNv
|
6
|
+
bS9lbmRwb2ludCIgQ29uc2VudD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6
|
7
|
+
Mi4wOmNvbnNlbnQ6dW5zcGVjaWZpZWQiIEluUmVzcG9uc2VUbz0iX2ZjNGEz
|
8
|
+
NGIwLTdlZmItMDEyZS1jYWFlLTc4MmJjYjEzYmIzOCI+CiAgPElzc3VlciB4
|
9
|
+
bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI+
|
10
|
+
aHR0cDovL2xvZ2luLmV4YW1wbGUuY29tL2lzc3VlcjwvSXNzdWVyPgogIDxz
|
11
|
+
YW1scDpTdGF0dXM+CiAgICA8c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJu
|
12
|
+
Om9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8+CiAg
|
13
|
+
PC9zYW1scDpTdGF0dXM+CiAgPEFzc2VydGlvbiB4bWxucz0idXJuOm9hc2lz
|
14
|
+
Om5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9Il83MjFiNGE1YS1k
|
15
|
+
N2UxLTQ4NjEtOTc1NC1hOWIxOTdiNmY5YWIiIElzc3VlSW5zdGFudD0iMjAx
|
16
|
+
MS0wNi0yMlQxMjo0OTozMC4zNDhaIiBWZXJzaW9uPSIyLjAiPgogICAgPElz
|
17
|
+
c3Vlcj5odHRwOi8vbG9naW4uZXhhbXBsZS5jb20vaXNzdWVyPC9Jc3N1ZXI+
|
18
|
+
CiAgICA8ZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9y
|
19
|
+
Zy8yMDAwLzA5L3htbGRzaWcjIj4KICAgICAgPGRzOlNpZ25lZEluZm8+CiAg
|
20
|
+
ICAgICAgPGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJo
|
21
|
+
dHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz4KICAg
|
22
|
+
ICAgICA8ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3
|
23
|
+
dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPgog
|
24
|
+
ICAgICAgIDxkczpSZWZlcmVuY2UgVVJJPSIjXzcyMWI0YTVhLWQ3ZTEtNDg2
|
25
|
+
MS05NzU0LWE5YjE5N2I2ZjlhYiI+CiAgICAgICAgICA8ZHM6VHJhbnNmb3Jt
|
26
|
+
cz4KICAgICAgICAgICAgPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6
|
27
|
+
Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0
|
28
|
+
dXJlIi8+CiAgICAgICAgICAgIDxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJo
|
29
|
+
dHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz4KICAg
|
30
|
+
ICAgICAgIDwvZHM6VHJhbnNmb3Jtcz4KICAgICAgICAgIDxkczpEaWdlc3RN
|
31
|
+
ZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3ht
|
32
|
+
bGVuYyNzaGEyNTYiLz4KICAgICAgICAgIDxkczpEaWdlc3RWYWx1ZT52NTN3
|
33
|
+
cW80ZllESzhVY3JPVWNPV2cyemxKL2NIVnVtWVMwS2pycm5WdUprPTwvZHM6
|
34
|
+
RGlnZXN0VmFsdWU+CiAgICAgICAgPC9kczpSZWZlcmVuY2U+CiAgICAgIDwv
|
35
|
+
ZHM6U2lnbmVkSW5mbz4KICAgICAgPGRzOlNpZ25hdHVyZVZhbHVlPlowOXBl
|
36
|
+
d1k3ekZ2OTFobjkwbHgwRUVubE1HTkw5elVKWk14SVI2cW9mTFpPWk1sVG5Y
|
37
|
+
TjV6RnNmKzFYUFBJWVpMdzVsQ0dqanRtZE5seGR2NzJ6TkZsTVROUnFaN0lp
|
38
|
+
SXd2azVHUk0zenZBV3NOT1k2ZEI0YzVxamU0UkhxL2ZySkdCZ04vZ2VWeFZt
|
39
|
+
bjNMWmQ1WmNrdWh1UzFzN0ZKQW9MVWNaRUxKL25jZ1JEZGdqQUUrcjhHdGFO
|
40
|
+
a3U0VVRCUkdBZnRsMFBXbUFTMDdsbGU2bGFTVVBSQmRCRE5sVlN6R0FQT3lY
|
41
|
+
UDE2ZUkxOWJvbllMaGpiOHVoY0N0bWdicnJhbkpVVGxZc1htcnhvaGNGdW4r
|
42
|
+
eWZxVFdXd2l4OW1SUXRBdEFFOW5nSUUwVkRkTC9reFR0NktOb1B6d2tlajVW
|
43
|
+
eFNMRkFncTJ1M3JaTWN1WUdadTFIUT09PC9kczpTaWduYXR1cmVWYWx1ZT4K
|
44
|
+
ICAgICAgPEtleUluZm8geG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAv
|
45
|
+
MDkveG1sZHNpZyMiPgogICAgICAgIDxkczpYNTA5RGF0YT4KICAgICAgICAg
|
46
|
+
IDxkczpYNTA5Q2VydGlmaWNhdGU+TUlJQzVEQ0NBY3lnQXdJQkFnSVFOQlRr
|
47
|
+
dDdxaWNhcEtOc0lYTWNrOHhUQU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dL
|
48
|
+
Z1lEVlFRREV5TkJSRVpUSUZOcFoyNXBibWNnTFNCc2IyZHBiaTVrY21WemIz
|
49
|
+
VnlZMlZ6TG1OdmJUQWVGdzB4TVRBMk1UQXhPRFUyTURGYUZ3MHhNakEyTURr
|
50
|
+
eE9EVTJNREZhTUM0eExEQXFCZ05WQkFNVEkwRkVSbE1nVTJsbmJtbHVaeUF0
|
51
|
+
SUd4dloybHVMbVJ5WlhOdmRYSmpaWE11WTI5dE1JSUJJakFOQmdrcWhraUc5
|
52
|
+
dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBcTdBTURHbkJISUd3dDlLUHRM
|
53
|
+
RDBNMEVYR3VabldHQW1iNXAyRkRjRnp0SkhPSThXWVBxZVJwaHpWU0VrZ1h0
|
54
|
+
UEloNUp4M2VsUzZoVm43SFZqMld2eklENmpwQjQ1bzhpRGs4UFdnaTE0ZnhH
|
55
|
+
V0U1bzFQaUI4WHJlMWM1dnMySUc1YVBXSUQ1dUM2YkQwWGduTDk1TWdPOUhH
|
56
|
+
UFBTUVJGbnVqS05xekZRZHRvQkpJSmF3QWVEL2kveHM3RmpGazl4MWZBMEV5
|
57
|
+
TENuaCtlYWZmSXBvcmIrMXh4VzJENkQzbVJUZ2ZIeFhyV1I4VzRqSG5pZ2da
|
58
|
+
aHFkRGhVeHZFYWlRRlRiSU4yRCt6eUI3YVF3UUNIU0ZwZXJCYytSNUZsbGdu
|
59
|
+
R0FhK3NqYjZnMUZYYmVobUVHd1NheHdSWklEQWhqSVFtYTV3WDV5V0pEeEZ6
|
60
|
+
UjRwc1RlRlJRSURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFCekFQ
|
61
|
+
QzJRUStVdHZrcVFZMm8vam9IR3RudUx5Zmt3ZDc2NERjR0RsY1lLVktFYURD
|
62
|
+
dm5KeDNneXdSVU9ERVJoRGh1Zkpid3I3T29YVmRodzcwTnRURU11Z0pGcjI5
|
63
|
+
U2d4bjNDaVRpeVBGU0RHang5MTFhYkt4dEpTQkludkkwMEFqWCtWbElaaG95
|
64
|
+
ODNZWU9SWEZjeWIrVXZoMnIyU1pVM0FDTnA4TTNjWlI2SjFFREJoUEtZd0VF
|
65
|
+
VWs4TlRNbVpMM3ZXanFMWldUeVRUaFRyUUYvbEg5UENsdzlPMjl1d2lmaXEy
|
66
|
+
WHpTeVNyMy9QSHh6cE1Sa0w5YzRFaTQ1UURtYWdlckFVUndlcTVwVVc4QzNV
|
67
|
+
QVVqTExWY1hrLzJwZXZaRU43MFlndDVwMmZBZ3M4NE9KaERSS2lIR3BhcmlF
|
68
|
+
bWo0THNKR1pzcDdxRkpwbjErTWlqUmU8L2RzOlg1MDlDZXJ0aWZpY2F0ZT4K
|
69
|
+
ICAgICAgICA8L2RzOlg1MDlEYXRhPgogICAgICA8L0tleUluZm8+CiAgICA8
|
70
|
+
L2RzOlNpZ25hdHVyZT4KICAgIDxTdWJqZWN0PgogICAgICA8TmFtZUlEIEZv
|
71
|
+
cm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4xOm5hbWVpZC1mb3Jt
|
72
|
+
YXQ6ZW1haWxBZGRyZXNzIj5oZWxsb0BleGFtcGxlLmNvbTwvTmFtZUlEPgog
|
73
|
+
ICAgICA8U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpu
|
74
|
+
YW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPgogICAgICAgIDxTdWJqZWN0
|
75
|
+
Q29uZmlybWF0aW9uRGF0YSBJblJlc3BvbnNlVG89Il9mYzRhMzRiMC03ZWZi
|
76
|
+
LTAxMmUtY2FhZS03ODJiY2IxM2JiMzgiIE5vdE9uT3JBZnRlcj0iMjAxMS0w
|
77
|
+
Ni0yMlQxMjo1NDozMC4zNDhaIiBSZWNpcGllbnQ9Imh0dHBzOi8vc29tZW9u
|
78
|
+
ZS5leGFtcGxlLmNvbS9lbmRwb2ludCIvPgogICAgICA8L1N1YmplY3RDb25m
|
79
|
+
aXJtYXRpb24+CiAgICA8L1N1YmplY3Q+CiAgICA8Q29uZGl0aW9ucyBOb3RC
|
80
|
+
ZWZvcmU9IjIwMTEtMDYtMjJUMTI6NDk6MzAuMzMyWiIgTm90T25PckFmdGVy
|
81
|
+
PSIyMDExLTA2LTIyVDEzOjQ5OjMwLjMzMloiPgogICAgICA8QXVkaWVuY2VS
|
82
|
+
ZXN0cmljdGlvbj4KICAgICAgICA8QXVkaWVuY2U+ZXhhbXBsZS5jb208L0F1
|
83
|
+
ZGllbmNlPgogICAgICA8L0F1ZGllbmNlUmVzdHJpY3Rpb24+CiAgICA8L0Nv
|
84
|
+
bmRpdGlvbnM+CiAgICA8QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIy
|
85
|
+
MDExLTA2LTIyVDEyOjQ5OjMwLjExMloiIFNlc3Npb25JbmRleD0iXzcyMWI0
|
86
|
+
YTVhLWQ3ZTEtNDg2MS05NzU0LWE5YjE5N2I2ZjlhYiI+CiAgICAgIDxBdXRo
|
87
|
+
bkNvbnRleHQ+CiAgICAgICAgPEF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpv
|
88
|
+
YXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOlBhc3N3b3JkUHJv
|
89
|
+
dGVjdGVkVHJhbnNwb3J0PC9BdXRobkNvbnRleHRDbGFzc1JlZj4KICAgICAg
|
90
|
+
PC9BdXRobkNvbnRleHQ+CiAgICA8L0F1dGhuU3RhdGVtZW50PgogIDwvQXNz
|
91
|
+
ZXJ0aW9uPgo8L3NhbWxwOlJlc3BvbnNlPgo=
|
@@ -0,0 +1,56 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" Destination="https://example.hello.com/access/saml" ID="jVFQbyEpSfUwqhZtJtarIaGoshwuAQMDwLoiMhzJXsv" InResponseTo="cfeooghajnhofcmogakmlhpkohnmikicnfhdnjlc" IssueInstant="2011-06-21T13:54:38.661Z" Version="2.0">
|
3
|
+
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://idm.orademo.com</saml2:Issuer>
|
4
|
+
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
5
|
+
<ds:SignedInfo>
|
6
|
+
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
7
|
+
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
|
8
|
+
<ds:Reference URI="#jVFQbyEpSfUwqhZtJtarIaGoshwuAQMDwLoiMhzJXsv">
|
9
|
+
<ds:Transforms>
|
10
|
+
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
11
|
+
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
|
12
|
+
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
|
13
|
+
</ds:Transform>
|
14
|
+
</ds:Transforms>
|
15
|
+
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
|
16
|
+
<ds:DigestValue>uHuSry39P16Yh7srS32xESmj4Lw=</ds:DigestValue>
|
17
|
+
</ds:Reference>
|
18
|
+
</ds:SignedInfo>
|
19
|
+
<ds:SignatureValue>fdghdfggfd=</ds:SignatureValue>
|
20
|
+
<ds:KeyInfo>
|
21
|
+
<ds:X509Data>
|
22
|
+
<ds:X509Certificate>dfghjkl</ds:X509Certificate>
|
23
|
+
</ds:X509Data>
|
24
|
+
</ds:KeyInfo>
|
25
|
+
</ds:Signature>
|
26
|
+
<saml2p:Status>
|
27
|
+
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
|
28
|
+
</saml2p:Status>
|
29
|
+
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="emmCjammnYdAbMWDuMAJeZvQIMBayeeYqqwvQoDclKE" IssueInstant="2011-06-21T13:54:38.676Z" Version="2.0">
|
30
|
+
<saml2:Issuer>https://idm.orademo.com</saml2:Issuer>
|
31
|
+
<saml2:Subject>
|
32
|
+
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" NameQualifier="idp.example.org">someone@example.org</saml2:NameID>
|
33
|
+
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
|
34
|
+
<saml2:SubjectConfirmationData InResponseTo="cfeooghajnhofcmogakmlhpkohnmikicnfhdnjlc" NotOnOrAfter="2011-06-21T14:09:38.676Z" Recipient="https://example.hello.com/access/saml"/>
|
35
|
+
</saml2:SubjectConfirmation>
|
36
|
+
</saml2:Subject>
|
37
|
+
<saml2:Conditions NotBefore="2011-06-21T13:54:38.683Z" NotOnOrAfter="2011-06-21T14:09:38.683Z">
|
38
|
+
<saml2:AudienceRestriction>
|
39
|
+
<saml2:Audience>hello.com</saml2:Audience>
|
40
|
+
</saml2:AudienceRestriction>
|
41
|
+
</saml2:Conditions>
|
42
|
+
<saml2:AuthnStatement AuthnInstant="2011-06-21T13:54:38.685Z" SessionIndex="perdkjfskdjfksdiertusfsdfsddeurtherukjdfgkdffg">
|
43
|
+
<saml2:AuthnContext>
|
44
|
+
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
|
45
|
+
</saml2:AuthnContext>
|
46
|
+
</saml2:AuthnStatement>
|
47
|
+
<saml2:AttributeStatement>
|
48
|
+
<saml2:Attribute Name="FirstName">
|
49
|
+
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Someone</saml2:AttributeValue>
|
50
|
+
</saml2:Attribute>
|
51
|
+
<saml2:Attribute Name="LastName">
|
52
|
+
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Special</saml2:AttributeValue>
|
53
|
+
</saml2:Attribute>
|
54
|
+
</saml2:AttributeStatement>
|
55
|
+
</saml2:Assertion>
|
56
|
+
</saml2p:Response>
|
@@ -0,0 +1,71 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="pfxc32aed67-820f-4296-0c20-205a10dd5787" Version="2.0" IssueInstant="2011-06-17T14:54:14Z" Destination="https://example.hello.com/access/saml" InResponseTo="_57bcbf70-7b1f-012e-c821-782bcb13bb38">
|
3
|
+
<saml:Issuer>https://federate.example.net/saml/saml2/idp/metadata.php</saml:Issuer>
|
4
|
+
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
5
|
+
<ds:SignedInfo>
|
6
|
+
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
7
|
+
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
|
8
|
+
<ds:Reference URI="#pfxc32aed67-820f-4296-0c20-205a10dd5787">
|
9
|
+
<ds:Transforms>
|
10
|
+
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
11
|
+
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
12
|
+
</ds:Transforms>
|
13
|
+
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
|
14
|
+
<ds:DigestValue>dVJ592k5xPjCHBCMiJ8eZkPUiT8=</ds:DigestValue>
|
15
|
+
</ds:Reference>
|
16
|
+
</ds:SignedInfo>
|
17
|
+
<ds:SignatureValue>LHNK1FJfcOIUuWVKJmGABQ+W98+pQ==</ds:SignatureValue>
|
18
|
+
<ds:KeyInfo>
|
19
|
+
<ds:X509Data>
|
20
|
+
<ds:X509Certificate>MIIQmS6WmmIht3k=</ds:X509Certificate>
|
21
|
+
</ds:X509Data>
|
22
|
+
</ds:KeyInfo>
|
23
|
+
</ds:Signature>
|
24
|
+
<samlp:Status>
|
25
|
+
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
|
26
|
+
</samlp:Status>
|
27
|
+
<saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="pfx7841991c-c73f-4035-e2ee-c170c0e1d3e4" Version="2.0" IssueInstant="2011-06-17T14:54:14Z">
|
28
|
+
<saml:Issuer>https://federate.example.net/saml/saml2/idp/metadata.php</saml:Issuer>
|
29
|
+
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
30
|
+
<ds:SignedInfo>
|
31
|
+
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
32
|
+
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
|
33
|
+
<ds:Reference URI="#pfx7841991c-c73f-4035-e2ee-c170c0e1d3e4">
|
34
|
+
<ds:Transforms>
|
35
|
+
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
36
|
+
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
37
|
+
</ds:Transforms>
|
38
|
+
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
|
39
|
+
<ds:DigestValue>mi0IAultZkpsZa1XxGx9X4iAPQg=</ds:DigestValue>
|
40
|
+
</ds:Reference>
|
41
|
+
</ds:SignedInfo>
|
42
|
+
<ds:SignatureValue>LqkW39SOYbttYxlGhIBw==</ds:SignatureValue>
|
43
|
+
<ds:KeyInfo>
|
44
|
+
<ds:X509Data>
|
45
|
+
<ds:X509Certificate>MIIGmmIht3k=</ds:X509Certificate>
|
46
|
+
</ds:X509Data>
|
47
|
+
</ds:KeyInfo>
|
48
|
+
</ds:Signature>
|
49
|
+
<saml:Subject>
|
50
|
+
<saml:NameID SPNameQualifier="hello.com" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">someone@example.com</saml:NameID>
|
51
|
+
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
|
52
|
+
<saml:SubjectConfirmationData NotOnOrAfter="2011-06-17T14:59:14Z" Recipient="https://example.hello.com/access/saml" InResponseTo="_57bcbf70-7b1f-012e-c821-782bcb13bb38"/>
|
53
|
+
</saml:SubjectConfirmation>
|
54
|
+
</saml:Subject>
|
55
|
+
<saml:Conditions NotBefore="2011-06-17T14:53:44Z" NotOnOrAfter="2011-06-17T14:59:14Z">
|
56
|
+
<saml:AudienceRestriction>
|
57
|
+
<saml:Audience>hello.com</saml:Audience>
|
58
|
+
</saml:AudienceRestriction>
|
59
|
+
</saml:Conditions>
|
60
|
+
<saml:AuthnStatement AuthnInstant="2011-06-17T14:54:07Z" SessionNotOnOrAfter="2011-06-17T22:54:14Z" SessionIndex="_51be37965feb5579d803141076936dc2e9d1d98ebf">
|
61
|
+
<saml:AuthnContext>
|
62
|
+
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
|
63
|
+
</saml:AuthnContext>
|
64
|
+
</saml:AuthnStatement>
|
65
|
+
<saml:AttributeStatement>
|
66
|
+
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
|
67
|
+
<saml:AttributeValue xsi:type="xs:string">someone@example.com</saml:AttributeValue>
|
68
|
+
</saml:Attribute>
|
69
|
+
</saml:AttributeStatement>
|
70
|
+
</saml:Assertion>
|
71
|
+
</samlp:Response>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
|
+
|
3
|
+
class SettingsTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "Settings" do
|
6
|
+
setup do
|
7
|
+
@settings = Onelogin::Saml::Settings.new
|
8
|
+
end
|
9
|
+
should "should provide getters and settings" do
|
10
|
+
accessors = [
|
11
|
+
:assertion_consumer_service_url, :issuer, :sp_name_qualifier, :sp_name_qualifier,
|
12
|
+
:idp_sso_target_url, :idp_cert_fingerprint, :name_identifier_format
|
13
|
+
]
|
14
|
+
|
15
|
+
accessors.each do |accessor|
|
16
|
+
value = Kernel.rand
|
17
|
+
@settings.send("#{accessor}=".to_sym, value)
|
18
|
+
assert_equal value, @settings.send(accessor)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -2,12 +2,22 @@ require 'rubygems'
|
|
2
2
|
require 'test/unit'
|
3
3
|
require 'shoulda'
|
4
4
|
require 'mocha'
|
5
|
+
require 'ruby-debug'
|
5
6
|
|
6
7
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
8
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
9
|
require 'ruby-saml'
|
9
10
|
|
10
11
|
class Test::Unit::TestCase
|
12
|
+
def fixture(document, base64 = true)
|
13
|
+
response = Dir.glob(File.join(File.dirname(__FILE__), "responses", "#{document}*")).first
|
14
|
+
if base64 && response =~ /\.xml$/
|
15
|
+
Base64.encode64(File.read(response))
|
16
|
+
else
|
17
|
+
File.read(response)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
11
21
|
def response_document
|
12
22
|
@response_document ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response1.xml.base64'))
|
13
23
|
end
|
data/test/xml_security_test.rb
CHANGED
@@ -10,7 +10,7 @@ class XmlSecurityTest < Test::Unit::TestCase
|
|
10
10
|
|
11
11
|
should "should run validate without throwing NS related exceptions" do
|
12
12
|
base64cert = @document.elements["//ds:X509Certificate"].text
|
13
|
-
@document.validate_doc(base64cert,
|
13
|
+
@document.validate_doc(base64cert, true)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-saml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 0.4.
|
9
|
+
- 6
|
10
|
+
version: 0.4.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- OneLogin LLC
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-06-
|
18
|
+
date: 2011-06-28 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -63,7 +63,7 @@ dependencies:
|
|
63
63
|
type: :development
|
64
64
|
version_requirements: *id003
|
65
65
|
- !ruby/object:Gem::Dependency
|
66
|
-
name:
|
66
|
+
name: ruby-debug
|
67
67
|
prerelease: false
|
68
68
|
requirement: &id004 !ruby/object:Gem::Requirement
|
69
69
|
none: false
|
@@ -76,6 +76,20 @@ dependencies:
|
|
76
76
|
version: "0"
|
77
77
|
type: :development
|
78
78
|
version_requirements: *id004
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: mocha
|
81
|
+
prerelease: false
|
82
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
type: :development
|
92
|
+
version_requirements: *id005
|
79
93
|
description: SAML toolkit for Ruby on Rails
|
80
94
|
email: support@onelogin.com
|
81
95
|
executables: []
|
@@ -96,16 +110,22 @@ files:
|
|
96
110
|
- lib/onelogin/saml/authrequest.rb
|
97
111
|
- lib/onelogin/saml/response.rb
|
98
112
|
- lib/onelogin/saml/settings.rb
|
113
|
+
- lib/onelogin/saml/validation_error.rb
|
99
114
|
- lib/ruby-saml.rb
|
100
115
|
- lib/xml_security.rb
|
101
116
|
- ruby-saml.gemspec
|
117
|
+
- test/request_test.rb
|
118
|
+
- test/response_test.rb
|
119
|
+
- test/responses/adfs_response.xml.base64
|
102
120
|
- test/responses/certificate1
|
121
|
+
- test/responses/open_saml_response.xml
|
103
122
|
- test/responses/response1.xml.base64
|
104
123
|
- test/responses/response2.xml.base64
|
105
124
|
- test/responses/response3.xml.base64
|
106
125
|
- test/responses/response4.xml.base64
|
107
126
|
- test/responses/response5.xml.base64
|
108
|
-
- test/
|
127
|
+
- test/responses/simple_saml_php.xml
|
128
|
+
- test/settings_test.rb
|
109
129
|
- test/test_helper.rb
|
110
130
|
- test/xml_security_test.rb
|
111
131
|
has_rdoc: true
|
@@ -143,6 +163,8 @@ signing_key:
|
|
143
163
|
specification_version: 3
|
144
164
|
summary: SAML Ruby Tookit
|
145
165
|
test_files:
|
146
|
-
- test/
|
166
|
+
- test/request_test.rb
|
167
|
+
- test/response_test.rb
|
168
|
+
- test/settings_test.rb
|
147
169
|
- test/test_helper.rb
|
148
170
|
- test/xml_security_test.rb
|