ruby-saml 0.9 → 0.9.1
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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/Gemfile +0 -21
- data/README.md +8 -2
- data/changelog.md +4 -0
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/ruby-saml.gemspec +30 -2
- data/test/idp_metadata_parser_test.rb +7 -7
- data/test/logoutrequest_test.rb +19 -31
- data/test/logoutresponse_test.rb +22 -28
- data/test/metadata_test.rb +69 -68
- data/test/request_test.rb +23 -23
- data/test/response_test.rb +67 -67
- data/test/settings_test.rb +8 -9
- data/test/slo_logoutrequest_test.rb +15 -16
- data/test/slo_logoutresponse_test.rb +12 -25
- data/test/test_helper.rb +36 -2
- data/test/xml_security_test.rb +42 -47
- metadata +105 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 472b9871eb65dc7e7290cd0eeefbe32299062339
|
4
|
+
data.tar.gz: 6275d19b96066aa9f17502b4e521b2c3d30626a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2f4796bb5f8ee71f40fdf18f28552038c0c9b6ac85f626452a2614a898f60775fdf482eab044f8643c178da126ea3d640eb3b72427c86e59b935418649ae5b8
|
7
|
+
data.tar.gz: 96050fa0bfb1451640fe4e1fa799b60fffee4f33622832e9f2a3c0bee20b085c8f99d087b1541d60277de4c4a88c01890206dca8b16c29f4d2dbbe5106b4666f
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -4,24 +4,3 @@
|
|
4
4
|
source 'http://rubygems.org'
|
5
5
|
|
6
6
|
gemspec
|
7
|
-
|
8
|
-
group :test do
|
9
|
-
if RUBY_VERSION < '1.9'
|
10
|
-
gem 'nokogiri', '~> 1.5.0'
|
11
|
-
gem 'ruby-debug', '~> 0.10.4'
|
12
|
-
elsif RUBY_VERSION < '2.0'
|
13
|
-
gem 'debugger-linecache', '~> 1.2.0'
|
14
|
-
gem 'debugger', '~> 1.6.4'
|
15
|
-
elsif RUBY_VERSION < '2.1'
|
16
|
-
gem 'byebug', '~> 2.1.1'
|
17
|
-
else
|
18
|
-
gem 'pry-byebug'
|
19
|
-
end
|
20
|
-
|
21
|
-
gem 'mocha', '~> 0.14', :require => false
|
22
|
-
gem 'rake', '~> 10'
|
23
|
-
gem 'shoulda', '~> 2.11'
|
24
|
-
gem 'systemu', '~> 2'
|
25
|
-
gem 'test-unit', '~> 3'
|
26
|
-
gem 'timecop', '<= 0.6.0'
|
27
|
-
end
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Ruby SAML [](http://travis-ci.org/onelogin/ruby-saml)
|
2
2
|
|
3
|
-
## Updating from 0.8.x to 0.9
|
3
|
+
## Updating from 0.8.x to 0.9.x
|
4
4
|
Version `0.9` adds many new features and improvements. It is a recommended update for all Ruby SAML users. For more details, please review [the changelog](changelog.md)
|
5
5
|
|
6
6
|
## Updating from 0.7.x to 0.8.x
|
@@ -14,6 +14,12 @@ SAML authorization is a two step process and you are expected to implement suppo
|
|
14
14
|
|
15
15
|
We created a demo project for Rails4 that uses the latest version of this library: [ruby-saml-example](https://github.com/onelogin/ruby-saml-example)
|
16
16
|
|
17
|
+
### Supported versions of Ruby
|
18
|
+
* 1.8.7
|
19
|
+
* 1.9.x
|
20
|
+
* 2.1.x
|
21
|
+
* 2.2 (not yet officially supported)
|
22
|
+
|
17
23
|
## Adding Features, Pull Requests
|
18
24
|
* Fork the repository
|
19
25
|
* Make your feature addition or bug fix
|
@@ -29,7 +35,7 @@ Using `Gemfile`
|
|
29
35
|
|
30
36
|
```ruby
|
31
37
|
# latest stable
|
32
|
-
gem 'ruby-saml', '~> 0.9'
|
38
|
+
gem 'ruby-saml', '~> 0.9.1'
|
33
39
|
|
34
40
|
# or track master for bleeding-edge
|
35
41
|
gem 'ruby-saml', :github => 'onelogin/ruby-saml'
|
data/changelog.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
# RubySaml Changelog
|
2
|
+
### 0.9.1 (Feb 10, 2015)
|
3
|
+
* [#194](https://github.com/onelogin/ruby-saml/pull/194) Relax nokogiri gem requirements
|
4
|
+
* [#191](https://github.com/onelogin/ruby-saml/pull/191) Use Minitest instead of Test::Unit
|
5
|
+
|
2
6
|
### 0.9 (Jan 26, 2015)
|
3
7
|
* [#169](https://github.com/onelogin/ruby-saml/pull/169) WantAssertionSigned should be either true or false
|
4
8
|
* [#167](https://github.com/onelogin/ruby-saml/pull/167) (doc update) make unit of clock drift obvious
|
data/ruby-saml.gemspec
CHANGED
@@ -21,9 +21,37 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.rdoc_options = ["--charset=UTF-8"]
|
22
22
|
s.require_paths = ["lib"]
|
23
23
|
s.rubygems_version = %q{1.3.7}
|
24
|
+
s.required_ruby_version = '>= 1.8.7'
|
24
25
|
s.summary = %q{SAML Ruby Tookit}
|
25
26
|
s.test_files = `git ls-files test/*`.split("\n")
|
26
27
|
|
27
|
-
s.add_runtime_dependency(
|
28
|
-
|
28
|
+
s.add_runtime_dependency('uuid', '~> 2.3')
|
29
|
+
if RUBY_VERSION < '1.9'
|
30
|
+
# 1.8.7
|
31
|
+
s.add_runtime_dependency('nokogiri', '~> 1.5.10')
|
32
|
+
else
|
33
|
+
s.add_runtime_dependency('nokogiri', '~> 1.6.0')
|
34
|
+
end
|
35
|
+
|
36
|
+
s.add_development_dependency('minitest', '~> 5.5')
|
37
|
+
s.add_development_dependency('mocha', '~> 0.14')
|
38
|
+
s.add_development_dependency('rake', '~> 10')
|
39
|
+
s.add_development_dependency('shoulda', '~> 2.11')
|
40
|
+
s.add_development_dependency('systemu', '~> 2')
|
41
|
+
s.add_development_dependency('timecop', '<= 0.6.0')
|
42
|
+
|
43
|
+
if RUBY_VERSION < '1.9'
|
44
|
+
# 1.8.7
|
45
|
+
s.add_development_dependency('ruby-debug', '~> 0.10.4')
|
46
|
+
elsif RUBY_VERSION < '2.0'
|
47
|
+
# 1.9.x
|
48
|
+
s.add_development_dependency('debugger-linecache', '~> 1.2.0')
|
49
|
+
s.add_development_dependency('debugger', '~> 1.6.4')
|
50
|
+
elsif RUBY_VERSION < '2.1'
|
51
|
+
# 2.0.x
|
52
|
+
s.add_development_dependency('byebug', '~> 2.1.1')
|
53
|
+
else
|
54
|
+
# 2.1.x, 2.2.x
|
55
|
+
s.add_development_dependency('pry-byebug')
|
56
|
+
end
|
29
57
|
end
|
@@ -2,14 +2,14 @@ require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
|
2
2
|
require 'net/http'
|
3
3
|
require 'net/https'
|
4
4
|
|
5
|
-
class IdpMetadataParserTest < Test
|
5
|
+
class IdpMetadataParserTest < Minitest::Test
|
6
6
|
|
7
7
|
class MockResponse
|
8
8
|
attr_accessor :body
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
describe "parsing an IdP descriptor file" do
|
12
|
+
it "extract settings details from xml" do
|
13
13
|
idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
|
14
14
|
|
15
15
|
settings = idp_metadata_parser.parse(idp_metadata)
|
@@ -20,8 +20,8 @@ class IdpMetadataParserTest < Test::Unit::TestCase
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
describe "download and parse IdP descriptor file" do
|
24
|
+
before do
|
25
25
|
mock_response = MockResponse.new
|
26
26
|
mock_response.body = idp_metadata
|
27
27
|
@url = "https://example.com"
|
@@ -33,7 +33,7 @@ class IdpMetadataParserTest < Test::Unit::TestCase
|
|
33
33
|
end
|
34
34
|
|
35
35
|
|
36
|
-
|
36
|
+
it "extract settings from remote xml" do
|
37
37
|
idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
|
38
38
|
settings = idp_metadata_parser.parse_remote(@url)
|
39
39
|
|
@@ -43,7 +43,7 @@ class IdpMetadataParserTest < Test::Unit::TestCase
|
|
43
43
|
assert_equal OpenSSL::SSL::VERIFY_PEER, @http.verify_mode
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
it "accept self signed certificate if insturcted" do
|
47
47
|
idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
|
48
48
|
settings = idp_metadata_parser.parse_remote(@url, false)
|
49
49
|
|
data/test/logoutrequest_test.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
|
3
|
-
class RequestTest < Test
|
3
|
+
class RequestTest < Minitest::Test
|
4
4
|
|
5
|
-
|
6
|
-
settings
|
5
|
+
describe "Logoutrequest" do
|
6
|
+
let(:settings) { OneLogin::RubySaml::Settings.new }
|
7
7
|
|
8
|
-
|
8
|
+
it "create the deflated SAMLRequest URL parameter" do
|
9
9
|
settings.idp_slo_target_url = "http://unauth.com/logout"
|
10
10
|
settings.name_identifier_value = "f00f00"
|
11
11
|
|
@@ -17,8 +17,8 @@ class RequestTest < Test::Unit::TestCase
|
|
17
17
|
assert_match /^<samlp:LogoutRequest/, inflated
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
it "support additional params" do
|
21
|
+
settings.idp_slo_target_url = "http://example.com"
|
22
22
|
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :hello => nil })
|
23
23
|
assert unauth_url =~ /&hello=$/
|
24
24
|
|
@@ -26,7 +26,7 @@ class RequestTest < Test::Unit::TestCase
|
|
26
26
|
assert unauth_url =~ /&foo=bar$/
|
27
27
|
end
|
28
28
|
|
29
|
-
|
29
|
+
it "set sessionindex" do
|
30
30
|
settings.idp_slo_target_url = "http://example.com"
|
31
31
|
sessionidx = UUID.new.generate
|
32
32
|
settings.sessionindex = sessionidx
|
@@ -38,7 +38,7 @@ class RequestTest < Test::Unit::TestCase
|
|
38
38
|
assert_match %r(#{sessionidx}</samlp:SessionIndex>), inflated
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
it "set name_identifier_value" do
|
42
42
|
settings = OneLogin::RubySaml::Settings.new
|
43
43
|
settings.idp_slo_target_url = "http://example.com"
|
44
44
|
settings.name_identifier_format = "transient"
|
@@ -52,8 +52,8 @@ class RequestTest < Test::Unit::TestCase
|
|
52
52
|
assert_match %r(#{name_identifier_value}</saml:NameID>), inflated
|
53
53
|
end
|
54
54
|
|
55
|
-
|
56
|
-
|
55
|
+
describe "when the target url doesn't contain a query string" do
|
56
|
+
it "create the SAMLRequest parameter correctly" do
|
57
57
|
settings = OneLogin::RubySaml::Settings.new
|
58
58
|
settings.idp_slo_target_url = "http://example.com"
|
59
59
|
settings.name_identifier_value = "f00f00"
|
@@ -63,8 +63,8 @@ class RequestTest < Test::Unit::TestCase
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
-
|
67
|
-
|
66
|
+
describe "when the target url contains a query string" do
|
67
|
+
it "create the SAMLRequest parameter correctly" do
|
68
68
|
settings = OneLogin::RubySaml::Settings.new
|
69
69
|
settings.idp_slo_target_url = "http://example.com?field=value"
|
70
70
|
settings.name_identifier_value = "f00f00"
|
@@ -74,8 +74,8 @@ class RequestTest < Test::Unit::TestCase
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
|
78
|
-
|
77
|
+
describe "consumation of logout may need to track the transaction" do
|
78
|
+
it "have access to the request uuid" do
|
79
79
|
settings = OneLogin::RubySaml::Settings.new
|
80
80
|
settings.idp_slo_target_url = "http://example.com?field=value"
|
81
81
|
settings.name_identifier_value = "f00f00"
|
@@ -88,8 +88,8 @@ class RequestTest < Test::Unit::TestCase
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
|
92
|
-
|
91
|
+
describe "when the settings indicate to sign (embebed) the logout request" do
|
92
|
+
it "created a signed logout request" do
|
93
93
|
settings = OneLogin::RubySaml::Settings.new
|
94
94
|
settings.idp_slo_target_url = "http://example.com?field=value"
|
95
95
|
settings.name_identifier_value = "f00f00"
|
@@ -106,7 +106,7 @@ class RequestTest < Test::Unit::TestCase
|
|
106
106
|
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
|
107
107
|
end
|
108
108
|
|
109
|
-
|
109
|
+
it "create a signed logout request with 256 digest and signature methods" do
|
110
110
|
settings = OneLogin::RubySaml::Settings.new
|
111
111
|
settings.compress_request = false
|
112
112
|
settings.idp_slo_target_url = "http://example.com?field=value"
|
@@ -128,8 +128,8 @@ class RequestTest < Test::Unit::TestCase
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
-
|
132
|
-
|
131
|
+
describe "when the settings indicate to sign the logout request" do
|
132
|
+
it "create a signature parameter" do
|
133
133
|
settings = OneLogin::RubySaml::Settings.new
|
134
134
|
settings.compress_request = false
|
135
135
|
settings.idp_slo_target_url = "http://example.com?field=value"
|
@@ -153,16 +153,4 @@ class RequestTest < Test::Unit::TestCase
|
|
153
153
|
end
|
154
154
|
|
155
155
|
end
|
156
|
-
|
157
|
-
def decode_saml_request_payload(unauth_url)
|
158
|
-
payload = CGI.unescape(unauth_url.split("SAMLRequest=").last)
|
159
|
-
decoded = Base64.decode64(payload)
|
160
|
-
|
161
|
-
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
162
|
-
inflated = zstream.inflate(decoded)
|
163
|
-
zstream.finish
|
164
|
-
zstream.close
|
165
|
-
inflated
|
166
|
-
end
|
167
|
-
|
168
156
|
end
|
data/test/logoutresponse_test.rb
CHANGED
@@ -1,26 +1,27 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
require 'rexml/document'
|
3
3
|
require 'responses/logoutresponse_fixtures'
|
4
|
-
class RubySamlTest < Test::Unit::TestCase
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
class RubySamlTest < Minitest::Test
|
6
|
+
|
7
|
+
describe "Logoutresponse" do
|
8
|
+
describe "#new" do
|
9
|
+
it "raise an exception when response is initialized with nil" do
|
9
10
|
assert_raises(ArgumentError) { OneLogin::RubySaml::Logoutresponse.new(nil) }
|
10
11
|
end
|
11
|
-
|
12
|
+
it "default to empty settings" do
|
12
13
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new( valid_response)
|
13
14
|
assert_nil logoutresponse.settings
|
14
15
|
end
|
15
|
-
|
16
|
+
it "accept constructor-injected settings" do
|
16
17
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, settings)
|
17
|
-
|
18
|
+
refute_nil logoutresponse.settings
|
18
19
|
end
|
19
|
-
|
20
|
+
it "accept constructor-injected options" do
|
20
21
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, nil, { :foo => :bar} )
|
21
22
|
assert !logoutresponse.options.empty?
|
22
23
|
end
|
23
|
-
|
24
|
+
it "support base64 encoded responses" do
|
24
25
|
expected_response = valid_response
|
25
26
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(Base64.encode64(expected_response), settings)
|
26
27
|
|
@@ -28,8 +29,8 @@ class RubySamlTest < Test::Unit::TestCase
|
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
describe "#validate" do
|
33
|
+
it "validate the response" do
|
33
34
|
in_relation_to_request_id = random_id
|
34
35
|
|
35
36
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response({:uuid => in_relation_to_request_id}), settings)
|
@@ -42,7 +43,7 @@ class RubySamlTest < Test::Unit::TestCase
|
|
42
43
|
assert logoutresponse.success?
|
43
44
|
end
|
44
45
|
|
45
|
-
|
46
|
+
it "invalidate responses with wrong id when given option :matches_uuid" do
|
46
47
|
|
47
48
|
expected_request_id = "_some_other_expected_uuid"
|
48
49
|
opts = { :matches_request_id => expected_request_id}
|
@@ -50,10 +51,10 @@ class RubySamlTest < Test::Unit::TestCase
|
|
50
51
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, settings, opts)
|
51
52
|
|
52
53
|
assert !logoutresponse.validate
|
53
|
-
|
54
|
+
refute_equal expected_request_id, logoutresponse.in_response_to
|
54
55
|
end
|
55
56
|
|
56
|
-
|
57
|
+
it "invalidate responses with wrong request status" do
|
57
58
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, settings)
|
58
59
|
|
59
60
|
assert !logoutresponse.validate
|
@@ -61,8 +62,8 @@ class RubySamlTest < Test::Unit::TestCase
|
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
64
|
-
|
65
|
-
|
65
|
+
describe "#validate!" do
|
66
|
+
it "validates good responses" do
|
66
67
|
in_relation_to_request_id = random_id
|
67
68
|
|
68
69
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response({:uuid => in_relation_to_request_id}), settings)
|
@@ -70,7 +71,7 @@ class RubySamlTest < Test::Unit::TestCase
|
|
70
71
|
logoutresponse.validate!
|
71
72
|
end
|
72
73
|
|
73
|
-
|
74
|
+
it "raises validation error when matching for wrong request id" do
|
74
75
|
|
75
76
|
expected_request_id = "_some_other_expected_id"
|
76
77
|
opts = { :matches_request_id => expected_request_id}
|
@@ -80,37 +81,30 @@ class RubySamlTest < Test::Unit::TestCase
|
|
80
81
|
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
|
81
82
|
end
|
82
83
|
|
83
|
-
|
84
|
+
it "raise validation error for wrong request status" do
|
84
85
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, settings)
|
85
86
|
|
86
87
|
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
|
87
88
|
end
|
88
89
|
|
89
|
-
|
90
|
+
it "raise validation error when in bad state" do
|
90
91
|
# no settings
|
91
92
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response)
|
92
93
|
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
|
93
94
|
end
|
94
95
|
|
95
|
-
|
96
|
+
it "raise validation error when in lack of issuer setting" do
|
96
97
|
bad_settings = settings
|
97
98
|
bad_settings.issuer = nil
|
98
99
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, bad_settings)
|
99
100
|
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
|
100
101
|
end
|
101
102
|
|
102
|
-
|
103
|
+
it "raise error for invalid xml" do
|
103
104
|
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(invalid_xml_response, settings)
|
104
105
|
|
105
106
|
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
|
106
107
|
end
|
107
108
|
end
|
108
|
-
|
109
109
|
end
|
110
|
-
|
111
|
-
# logoutresponse fixtures
|
112
|
-
def random_id
|
113
|
-
"_#{UUID.new.generate}"
|
114
|
-
end
|
115
|
-
|
116
110
|
end
|
data/test/metadata_test.rb
CHANGED
@@ -1,87 +1,88 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
|
3
|
-
class MetadataTest < Test
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
should "generate Service Provider Metadata with X509Certificate" do
|
14
|
-
@settings.security[:authn_requests_signed] = true
|
15
|
-
@settings.certificate = ruby_saml_cert_text
|
3
|
+
class MetadataTest < Minitest::Test
|
4
|
+
|
5
|
+
describe 'Metadata' do
|
6
|
+
def setup
|
7
|
+
@settings = OneLogin::RubySaml::Settings.new
|
8
|
+
@settings.issuer = "https://example.com"
|
9
|
+
@settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
10
|
+
@settings.assertion_consumer_service_url = "https://foo.example/saml/consume"
|
11
|
+
@settings.security[:authn_requests_signed] = false
|
12
|
+
end
|
16
13
|
|
17
|
-
|
14
|
+
it "generates Service Provider Metadata with X509Certificate" do
|
15
|
+
@settings.security[:authn_requests_signed] = true
|
16
|
+
@settings.certificate = ruby_saml_cert_text
|
18
17
|
|
19
|
-
|
20
|
-
xml_doc = REXML::Document.new(xml_text)
|
18
|
+
xml_text = OneLogin::RubySaml::Metadata.new.generate(@settings)
|
21
19
|
|
22
|
-
|
23
|
-
|
20
|
+
# assert xml_text can be parsed into an xml doc
|
21
|
+
xml_doc = REXML::Document.new(xml_text)
|
24
22
|
|
25
|
-
|
26
|
-
"
|
27
|
-
"ds" => "http://www.w3.org/2000/09/xmldsig#"
|
28
|
-
})
|
29
|
-
cert_text = cert_node.text
|
30
|
-
cert = OpenSSL::X509::Certificate.new(Base64.decode64(cert_text))
|
31
|
-
assert_equal ruby_saml_cert.to_der, cert.to_der
|
32
|
-
end
|
23
|
+
spsso_descriptor = REXML::XPath.first(xml_doc, "//md:SPSSODescriptor")
|
24
|
+
assert_equal "true", spsso_descriptor.attribute("AuthnRequestsSigned").value
|
33
25
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
26
|
+
cert_node = REXML::XPath.first(xml_doc, "//md:KeyDescriptor/ds:KeyInfo/ds:X509Data/ds:X509Certificate", {
|
27
|
+
"md" => "urn:oasis:names:tc:SAML:2.0:metadata",
|
28
|
+
"ds" => "http://www.w3.org/2000/09/xmldsig#"
|
29
|
+
})
|
30
|
+
cert_text = cert_node.text
|
31
|
+
cert = OpenSSL::X509::Certificate.new(Base64.decode64(cert_text))
|
32
|
+
assert_equal ruby_saml_cert.to_der, cert.to_der
|
33
|
+
end
|
40
34
|
|
41
|
-
|
35
|
+
it "generates Service Provider Metadata" do
|
36
|
+
settings = OneLogin::RubySaml::Settings.new
|
37
|
+
settings.issuer = "https://example.com"
|
38
|
+
settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
39
|
+
settings.assertion_consumer_service_url = "https://foo.example/saml/consume"
|
40
|
+
settings.security[:authn_requests_signed] = false
|
42
41
|
|
43
|
-
|
44
|
-
start = "<?xml version='1.0' encoding='UTF-8'?>\n<md:EntityDescriptor"
|
45
|
-
assert xml_text[0..start.length-1] == start
|
42
|
+
xml_text = OneLogin::RubySaml::Metadata.new.generate(settings)
|
46
43
|
|
47
|
-
|
48
|
-
|
44
|
+
# assert correct xml declaration
|
45
|
+
start = "<?xml version='1.0' encoding='UTF-8'?>\n<md:EntityDescriptor"
|
46
|
+
assert xml_text[0..start.length-1] == start
|
49
47
|
|
50
|
-
|
48
|
+
# assert xml_text can be parsed into an xml doc
|
49
|
+
xml_doc = REXML::Document.new(xml_text)
|
51
50
|
|
52
|
-
|
53
|
-
assert_equal "urn:oasis:names:tc:SAML:2.0:protocol", spsso_descriptor.attribute("protocolSupportEnumeration").value
|
54
|
-
assert_equal "false", spsso_descriptor.attribute("AuthnRequestsSigned").value
|
55
|
-
assert_equal "false", spsso_descriptor.attribute("WantAssertionsSigned").value
|
51
|
+
assert_equal "https://example.com", REXML::XPath.first(xml_doc, "//md:EntityDescriptor").attribute("entityID").value
|
56
52
|
|
57
|
-
|
53
|
+
spsso_descriptor = REXML::XPath.first(xml_doc, "//md:SPSSODescriptor")
|
54
|
+
assert_equal "urn:oasis:names:tc:SAML:2.0:protocol", spsso_descriptor.attribute("protocolSupportEnumeration").value
|
55
|
+
assert_equal "false", spsso_descriptor.attribute("AuthnRequestsSigned").value
|
56
|
+
assert_equal "false", spsso_descriptor.attribute("WantAssertionsSigned").value
|
58
57
|
|
59
|
-
|
60
|
-
assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", acs.attribute("Binding").value
|
61
|
-
assert_equal "https://foo.example/saml/consume", acs.attribute("Location").value
|
62
|
-
end
|
58
|
+
assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", REXML::XPath.first(xml_doc, "//md:NameIDFormat").text.strip
|
63
59
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
68
|
-
settings.assertion_consumer_service_url = "https://foo.example/saml/consume"
|
69
|
-
settings.attribute_consuming_service.configure do
|
70
|
-
service_name "Test Service"
|
71
|
-
add_attribute(:name => "Name", :name_format => "Name Format", :friendly_name => "Friendly Name", :attribute_value => "Attribute Value")
|
60
|
+
acs = REXML::XPath.first(xml_doc, "//md:AssertionConsumerService")
|
61
|
+
assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", acs.attribute("Binding").value
|
62
|
+
assert_equal "https://foo.example/saml/consume", acs.attribute("Location").value
|
72
63
|
end
|
73
64
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
65
|
+
it "generates attribute service if configured" do
|
66
|
+
settings = OneLogin::RubySaml::Settings.new
|
67
|
+
settings.issuer = "https://example.com"
|
68
|
+
settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
69
|
+
settings.assertion_consumer_service_url = "https://foo.example/saml/consume"
|
70
|
+
settings.attribute_consuming_service.configure do
|
71
|
+
service_name "Test Service"
|
72
|
+
add_attribute(:name => "Name", :name_format => "Name Format", :friendly_name => "Friendly Name", :attribute_value => "Attribute Value")
|
73
|
+
end
|
74
|
+
|
75
|
+
xml_text = OneLogin::RubySaml::Metadata.new.generate(settings)
|
76
|
+
xml_doc = REXML::Document.new(xml_text)
|
77
|
+
acs = REXML::XPath.first(xml_doc, "//md:AttributeConsumingService")
|
78
|
+
assert_equal "true", acs.attribute("isDefault").value
|
79
|
+
assert_equal "1", acs.attribute("index").value
|
80
|
+
assert_equal REXML::XPath.first(xml_doc, "//md:ServiceName").text.strip, "Test Service"
|
81
|
+
req_attr = REXML::XPath.first(xml_doc, "//md:RequestedAttribute")
|
82
|
+
assert_equal "Name", req_attr.attribute("Name").value
|
83
|
+
assert_equal "Name Format", req_attr.attribute("NameFormat").value
|
84
|
+
assert_equal "Friendly Name", req_attr.attribute("FriendlyName").value
|
85
|
+
assert_equal "Attribute Value", REXML::XPath.first(xml_doc, "//md:AttributeValue").text.strip
|
86
|
+
end
|
85
87
|
end
|
86
|
-
|
87
88
|
end
|