saml_idp 0.14.0 → 0.15.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.
- checksums.yaml +4 -4
- data/README.md +7 -4
- data/lib/saml_idp/configurator.rb +2 -0
- data/lib/saml_idp/controller.rb +11 -7
- data/lib/saml_idp/request.rb +4 -3
- data/lib/saml_idp/response_builder.rb +12 -6
- data/lib/saml_idp/saml_response.rb +47 -34
- data/lib/saml_idp/version.rb +1 -1
- data/saml_idp.gemspec +26 -26
- data/spec/lib/saml_idp/assertion_builder_spec.rb +70 -0
- data/spec/lib/saml_idp/configurator_spec.rb +1 -0
- data/spec/lib/saml_idp/request_spec.rb +43 -9
- data/spec/lib/saml_idp/saml_response_spec.rb +103 -11
- data/spec/rails_app/app/controllers/saml_idp_controller.rb +50 -37
- data/spec/rails_app/config/application.rb +1 -0
- data/spec/rails_app/config/boot.rb +1 -1
- metadata +46 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4da444f25fd4d8cb2b53d847ee3ffa44adab3b2c4b64be57a6935c0922acf1a8
|
4
|
+
data.tar.gz: ff0beb64e76c37a0bbcb098f0bd5a50b4d15ff124d63d9c01d421f4693f6fa2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fe91e27e817106e66738c73c670ce064c18b18e9528f7aef3c2a4dc87658c9262877b7a62f491c29ff371d39e0306721bc1f97af7ec3fb6fd1d23b8550b32ce
|
7
|
+
data.tar.gz: d6ee196976da4fe1af818bca3183632372ef2e1e3059891e75a13dc39caa9fb86c3d312c384d926877f9e14cfbd751d566d517742e72e0bb77e276e446a88aed
|
data/README.md
CHANGED
@@ -42,10 +42,11 @@ Check out our Wiki page for Rails integration
|
|
42
42
|
|
43
43
|
#### Signed assertions and Signed Response
|
44
44
|
|
45
|
-
By default SAML Assertion will be signed with an algorithm which defined to `config.algorithm
|
45
|
+
By default SAML Assertion will be signed with an algorithm which defined to `config.algorithm`, because SAML assertions contain secure information used for authentication such as NameID.
|
46
|
+
Besides that, signing assertions could be optional and can be defined with `config.signed_assertion` option. Setting this configuration flag to `false` will add raw assertions on the response instead of signed ones. If the response is encrypted the `config.signed_assertion` will be ignored and all assertions will be signed.
|
46
47
|
|
47
48
|
Signing SAML Response is optional, but some security perspective SP services might require Response message itself must be signed.
|
48
|
-
For that, you can enable it with `
|
49
|
+
For that, you can enable it with `signed_message: true` option for `encode_response(user_email, signed_message: true)` method. [More about SAML spec](https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=68)
|
49
50
|
|
50
51
|
#### Signing algorithm
|
51
52
|
|
@@ -85,7 +86,9 @@ CERT
|
|
85
86
|
# config.attribute_service_location = "#{base}/saml/attributes"
|
86
87
|
# config.single_service_post_location = "#{base}/saml/auth"
|
87
88
|
# config.session_expiry = 86400 # Default: 0 which means never
|
88
|
-
# config.
|
89
|
+
# config.signed_assertion = false # Default: true which means signed assertions on the SAML Response
|
90
|
+
# config.compress = true # Default: false which means the SAML Response is not being compressed
|
91
|
+
# config.logger = ::Logger.new($stdout) # Default: if in Rails context - Rails.logger, else ->(msg) { puts msg }. Works with either a Ruby Logger or a lambda
|
89
92
|
|
90
93
|
# Principal (e.g. User) is passed in when you `encode_response`
|
91
94
|
#
|
@@ -219,7 +222,7 @@ The gem provides an helper to generate a fingerprint for a X.509 certificate.
|
|
219
222
|
The second parameter is optional and default to your configuration `SamlIdp.config.algorithm`
|
220
223
|
|
221
224
|
```ruby
|
222
|
-
Fingerprint.certificate_digest(x509_cert, :sha512)
|
225
|
+
SamlIdp::Fingerprint.certificate_digest(x509_cert, :sha512)
|
223
226
|
```
|
224
227
|
|
225
228
|
## Service Providers
|
@@ -22,6 +22,7 @@ module SamlIdp
|
|
22
22
|
attr_accessor :service_provider
|
23
23
|
attr_accessor :assertion_consumer_service_hosts
|
24
24
|
attr_accessor :session_expiry
|
25
|
+
attr_accessor :logger
|
25
26
|
|
26
27
|
def initialize
|
27
28
|
self.x509_certificate = Default::X509_CERTIFICATE
|
@@ -34,6 +35,7 @@ module SamlIdp
|
|
34
35
|
self.service_provider.persisted_metadata_getter = ->(id, service_provider) { }
|
35
36
|
self.session_expiry = 0
|
36
37
|
self.attributes = {}
|
38
|
+
self.logger = defined?(::Rails) ? Rails.logger : ->(msg) { puts msg }
|
37
39
|
end
|
38
40
|
|
39
41
|
# formats
|
data/lib/saml_idp/controller.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
require 'openssl'
|
3
2
|
require 'base64'
|
4
3
|
require 'time'
|
@@ -36,9 +35,8 @@ module SamlIdp
|
|
36
35
|
def validate_saml_request(raw_saml_request = params[:SAMLRequest])
|
37
36
|
decode_request(raw_saml_request)
|
38
37
|
return true if valid_saml_request?
|
39
|
-
|
40
|
-
|
41
|
-
end
|
38
|
+
|
39
|
+
head :forbidden if defined?(::Rails)
|
42
40
|
false
|
43
41
|
end
|
44
42
|
|
@@ -60,9 +58,13 @@ module SamlIdp
|
|
60
58
|
expiry = opts[:expiry] || 60*60
|
61
59
|
session_expiry = opts[:session_expiry]
|
62
60
|
encryption_opts = opts[:encryption] || nil
|
61
|
+
name_id_formats_opts = opts[:name_id_formats] || nil
|
62
|
+
asserted_attributes_opts = opts[:attributes] || nil
|
63
63
|
signed_message_opts = opts[:signed_message] || false
|
64
64
|
name_id_formats_opts = opts[:name_id_formats] || nil
|
65
65
|
asserted_attributes_opts = opts[:attributes] || nil
|
66
|
+
signed_assertion_opts = opts[:signed_assertion] || true
|
67
|
+
compress_opts = opts[:compress] || false
|
66
68
|
|
67
69
|
SamlResponse.new(
|
68
70
|
reference_id,
|
@@ -77,13 +79,15 @@ module SamlIdp
|
|
77
79
|
expiry,
|
78
80
|
encryption_opts,
|
79
81
|
session_expiry,
|
80
|
-
signed_message_opts,
|
81
82
|
name_id_formats_opts,
|
82
|
-
asserted_attributes_opts
|
83
|
+
asserted_attributes_opts,
|
84
|
+
signed_assertion_opts,
|
85
|
+
signed_message_opts,
|
86
|
+
compress_opts
|
83
87
|
).build
|
84
88
|
end
|
85
89
|
|
86
|
-
def encode_logout_response(
|
90
|
+
def encode_logout_response(_principal, opts = {})
|
87
91
|
SamlIdp::LogoutResponseBuilder.new(
|
88
92
|
get_saml_response_id,
|
89
93
|
(opts[:issuer_uri] || issuer_uri),
|
data/lib/saml_idp/request.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'saml_idp/xml_security'
|
2
2
|
require 'saml_idp/service_provider'
|
3
|
+
require 'logger'
|
3
4
|
module SamlIdp
|
4
5
|
class Request
|
5
6
|
def self.from_deflated_request(raw)
|
@@ -77,10 +78,10 @@ module SamlIdp
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def log(msg)
|
80
|
-
if
|
81
|
-
|
81
|
+
if config.logger.class <= ::Logger
|
82
|
+
config.logger.info msg
|
82
83
|
else
|
83
|
-
|
84
|
+
config.logger.call msg
|
84
85
|
end
|
85
86
|
end
|
86
87
|
|
@@ -23,21 +23,21 @@ module SamlIdp
|
|
23
23
|
self.raw_algorithm = raw_algorithm
|
24
24
|
end
|
25
25
|
|
26
|
-
def encoded(signed_message: false)
|
27
|
-
@encoded ||= signed_message ? encode_signed_message : encode_raw_message
|
26
|
+
def encoded(signed_message: false, compress: false)
|
27
|
+
@encoded ||= signed_message ? encode_signed_message(compress) : encode_raw_message(compress)
|
28
28
|
end
|
29
29
|
|
30
30
|
def raw
|
31
31
|
build
|
32
32
|
end
|
33
33
|
|
34
|
-
def encode_raw_message
|
35
|
-
Base64.strict_encode64(raw)
|
34
|
+
def encode_raw_message(compress)
|
35
|
+
Base64.strict_encode64(compress ? deflate(raw) : raw)
|
36
36
|
end
|
37
37
|
private :encode_raw_message
|
38
38
|
|
39
|
-
def encode_signed_message
|
40
|
-
Base64.strict_encode64(signed)
|
39
|
+
def encode_signed_message(compress)
|
40
|
+
Base64.strict_encode64(compress ? deflate(signed) : signed)
|
41
41
|
end
|
42
42
|
private :encode_signed_message
|
43
43
|
|
@@ -66,11 +66,17 @@ module SamlIdp
|
|
66
66
|
def response_id_string
|
67
67
|
"_#{response_id}"
|
68
68
|
end
|
69
|
+
alias_method :reference_id, :response_id
|
69
70
|
private :response_id_string
|
70
71
|
|
71
72
|
def now_iso
|
72
73
|
Time.now.utc.iso8601
|
73
74
|
end
|
74
75
|
private :now_iso
|
76
|
+
|
77
|
+
def deflate(inflated)
|
78
|
+
Zlib::Deflate.deflate(inflated, 9)[2..-5]
|
79
|
+
end
|
80
|
+
private :deflate
|
75
81
|
end
|
76
82
|
end
|
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'saml_idp/assertion_builder'
|
2
4
|
require 'saml_idp/response_builder'
|
3
5
|
module SamlIdp
|
4
6
|
class SamlResponse
|
5
|
-
attr_accessor :assertion_with_signature
|
6
7
|
attr_accessor :reference_id
|
7
8
|
attr_accessor :response_id
|
8
9
|
attr_accessor :issuer_uri
|
@@ -17,27 +18,32 @@ module SamlIdp
|
|
17
18
|
attr_accessor :expiry
|
18
19
|
attr_accessor :encryption_opts
|
19
20
|
attr_accessor :session_expiry
|
20
|
-
attr_accessor :signed_message_opts
|
21
21
|
attr_accessor :name_id_formats_opts
|
22
22
|
attr_accessor :asserted_attributes_opts
|
23
|
+
attr_accessor :signed_message_opts
|
24
|
+
attr_accessor :signed_assertion_opts
|
25
|
+
attr_accessor :compression_opts
|
23
26
|
|
24
27
|
def initialize(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
28
|
+
reference_id,
|
29
|
+
response_id,
|
30
|
+
issuer_uri,
|
31
|
+
principal,
|
32
|
+
audience_uri,
|
33
|
+
saml_request_id,
|
34
|
+
saml_acs_url,
|
35
|
+
algorithm,
|
36
|
+
authn_context_classref,
|
37
|
+
expiry = 60 * 60,
|
38
|
+
encryption_opts = nil,
|
39
|
+
session_expiry = 0,
|
40
|
+
name_id_formats_opts = nil,
|
41
|
+
asserted_attributes_opts = nil,
|
42
|
+
signed_message_opts = false,
|
43
|
+
signed_assertion_opts = true,
|
44
|
+
compression_opts = false
|
40
45
|
)
|
46
|
+
|
41
47
|
self.reference_id = reference_id
|
42
48
|
self.response_id = response_id
|
43
49
|
self.issuer_uri = issuer_uri
|
@@ -55,26 +61,32 @@ module SamlIdp
|
|
55
61
|
self.signed_message_opts = signed_message_opts
|
56
62
|
self.name_id_formats_opts = name_id_formats_opts
|
57
63
|
self.asserted_attributes_opts = asserted_attributes_opts
|
64
|
+
self.signed_assertion_opts = signed_assertion_opts
|
65
|
+
self.name_id_formats_opts = name_id_formats_opts
|
66
|
+
self.asserted_attributes_opts = asserted_attributes_opts
|
67
|
+
self.compression_opts = compression_opts
|
58
68
|
end
|
59
69
|
|
60
70
|
def build
|
61
|
-
@
|
71
|
+
@build ||= encoded_message
|
62
72
|
end
|
63
73
|
|
64
74
|
def signed_assertion
|
65
75
|
if encryption_opts
|
66
76
|
assertion_builder.encrypt(sign: true)
|
67
|
-
|
77
|
+
elsif signed_assertion_opts
|
68
78
|
assertion_builder.signed
|
79
|
+
else
|
80
|
+
assertion_builder.raw
|
69
81
|
end
|
70
82
|
end
|
71
83
|
private :signed_assertion
|
72
84
|
|
73
85
|
def encoded_message
|
74
86
|
if signed_message_opts
|
75
|
-
response_builder.encoded(signed_message: true)
|
87
|
+
response_builder.encoded(signed_message: true, compress: compression_opts)
|
76
88
|
else
|
77
|
-
response_builder.encoded(signed_message: false)
|
89
|
+
response_builder.encoded(signed_message: false, compress: compression_opts)
|
78
90
|
end
|
79
91
|
end
|
80
92
|
private :encoded_message
|
@@ -85,19 +97,20 @@ module SamlIdp
|
|
85
97
|
private :response_builder
|
86
98
|
|
87
99
|
def assertion_builder
|
88
|
-
@assertion_builder ||=
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
100
|
+
@assertion_builder ||=
|
101
|
+
AssertionBuilder.new SecureRandom.uuid,
|
102
|
+
issuer_uri,
|
103
|
+
principal,
|
104
|
+
audience_uri,
|
105
|
+
saml_request_id,
|
106
|
+
saml_acs_url,
|
107
|
+
algorithm,
|
108
|
+
authn_context_classref,
|
109
|
+
expiry,
|
110
|
+
encryption_opts,
|
111
|
+
session_expiry,
|
112
|
+
name_id_formats_opts,
|
113
|
+
asserted_attributes_opts
|
101
114
|
end
|
102
115
|
private :assertion_builder
|
103
116
|
end
|
data/lib/saml_idp/version.rb
CHANGED
data/saml_idp.gemspec
CHANGED
@@ -1,62 +1,62 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
4
|
+
require 'saml_idp/version'
|
4
5
|
|
5
6
|
Gem::Specification.new do |s|
|
6
7
|
s.name = %q{saml_idp}
|
7
8
|
s.version = SamlIdp::VERSION
|
8
9
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = [
|
10
|
+
s.authors = ['Jon Phenow']
|
10
11
|
s.email = 'jon.phenow@sportngin.com'
|
11
12
|
s.homepage = 'https://github.com/saml-idp/saml_idp'
|
12
13
|
s.summary = 'SAML Indentity Provider for Ruby'
|
13
14
|
s.description = 'SAML IdP (Identity Provider) Library for Ruby'
|
14
|
-
s.date = Time.now.utc.strftime(
|
15
|
+
s.date = Time.now.utc.strftime('%Y-%m-%d')
|
15
16
|
s.files = Dir['lib/**/*', 'LICENSE', 'README.md', 'Gemfile', 'saml_idp.gemspec']
|
16
17
|
s.required_ruby_version = '>= 2.5'
|
17
18
|
s.license = 'MIT'
|
18
19
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
20
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
-
s.require_paths = [
|
21
|
+
s.require_paths = ['lib']
|
21
22
|
s.rdoc_options = ['--charset=UTF-8']
|
22
23
|
s.metadata = {
|
23
|
-
'homepage_uri'
|
24
|
-
'source_code_uri'
|
25
|
-
'bug_tracker_uri'
|
24
|
+
'homepage_uri' => 'https://github.com/saml-idp/saml_idp',
|
25
|
+
'source_code_uri' => 'https://github.com/saml-idp/saml_idp',
|
26
|
+
'bug_tracker_uri' => 'https://github.com/saml-idp/saml_idp/issues',
|
26
27
|
'documentation_uri' => "http://rdoc.info/gems/saml_idp/#{SamlIdp::VERSION}"
|
27
28
|
}
|
28
29
|
|
29
30
|
s.post_install_message = <<-INST
|
30
|
-
If you're just recently updating saml_idp - please be aware we've changed the default
|
31
|
-
certificate. See the PR and a description of why we've done this here:
|
32
|
-
https://github.com/saml-idp/saml_idp/pull/29
|
33
|
-
|
34
|
-
If you just need to see the certificate `bundle open saml_idp` and go to
|
35
|
-
`lib/saml_idp/default.rb`
|
31
|
+
If you're just recently updating saml_idp - please be aware we've changed the default
|
32
|
+
certificate. See the PR and a description of why we've done this here:
|
33
|
+
https://github.com/saml-idp/saml_idp/pull/29
|
36
34
|
|
37
|
-
|
38
|
-
|
35
|
+
If you just need to see the certificate `bundle open saml_idp` and go to
|
36
|
+
`lib/saml_idp/default.rb`
|
39
37
|
|
40
|
-
|
38
|
+
Similarly, please see the README about certificates - you should avoid using the
|
39
|
+
defaults in a Production environment. Post any issues you to github.
|
41
40
|
|
42
|
-
|
43
|
-
|
41
|
+
** New in Version 0.3.0 **
|
42
|
+
Encrypted Assertions require the xmlenc gem. See the example in the Controller
|
43
|
+
section of the README.
|
44
44
|
INST
|
45
45
|
|
46
46
|
s.add_dependency('activesupport', '>= 5.2')
|
47
47
|
s.add_dependency('builder', '>= 3.0')
|
48
48
|
s.add_dependency('nokogiri', '>= 1.6.2')
|
49
|
-
s.add_dependency('xmlenc', '>= 0.7.1')
|
50
49
|
s.add_dependency('rexml')
|
50
|
+
s.add_dependency('xmlenc', '>= 0.7.1')
|
51
51
|
|
52
|
+
s.add_development_dependency('activeresource', '>= 5.1')
|
53
|
+
s.add_development_dependency('appraisal')
|
54
|
+
s.add_development_dependency('byebug')
|
55
|
+
s.add_development_dependency('capybara', '>= 2.16')
|
56
|
+
s.add_development_dependency('rails', '>= 5.2')
|
52
57
|
s.add_development_dependency('rake')
|
53
|
-
s.add_development_dependency('simplecov')
|
54
58
|
s.add_development_dependency('rspec', '>= 3.7.0')
|
55
59
|
s.add_development_dependency('ruby-saml', '>= 1.7.2')
|
56
|
-
s.add_development_dependency('
|
57
|
-
s.add_development_dependency('activeresource', '>= 5.1')
|
58
|
-
s.add_development_dependency('capybara', '>= 2.16')
|
60
|
+
s.add_development_dependency('simplecov')
|
59
61
|
s.add_development_dependency('timecop', '>= 0.8')
|
60
|
-
s.add_development_dependency('appraisal')
|
61
|
-
s.add_development_dependency('byebug')
|
62
62
|
end
|
@@ -199,5 +199,75 @@ module SamlIdp
|
|
199
199
|
expect(builder.session_expiry).to eq(8)
|
200
200
|
end
|
201
201
|
end
|
202
|
+
|
203
|
+
describe "with name_id_formats_opt" do
|
204
|
+
let(:name_id_formats_opt) {
|
205
|
+
{
|
206
|
+
persistent: -> (principal) {
|
207
|
+
principal.unique_identifier
|
208
|
+
}
|
209
|
+
}
|
210
|
+
}
|
211
|
+
it "delegates name_id_formats to opts" do
|
212
|
+
UserWithUniqueId = Struct.new(:unique_identifier, :email, :asserted_attributes)
|
213
|
+
principal = UserWithUniqueId.new('unique_identifier_123456', 'foo@example.com', { emailAddress: { getter: :email } })
|
214
|
+
builder = described_class.new(
|
215
|
+
reference_id,
|
216
|
+
issuer_uri,
|
217
|
+
principal,
|
218
|
+
audience_uri,
|
219
|
+
saml_request_id,
|
220
|
+
saml_acs_url,
|
221
|
+
algorithm,
|
222
|
+
authn_context_classref,
|
223
|
+
expiry,
|
224
|
+
encryption_opts,
|
225
|
+
session_expiry,
|
226
|
+
name_id_formats_opt,
|
227
|
+
asserted_attributes_opt
|
228
|
+
)
|
229
|
+
Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do
|
230
|
+
expect(builder.raw).to eq("<Assertion xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"_abc\" IssueInstant=\"2010-06-01T13:00:00Z\" Version=\"2.0\"><Issuer>http://sportngin.com</Issuer><Subject><NameID Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent\">unique_identifier_123456</NameID><SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><SubjectConfirmationData InResponseTo=\"123\" NotOnOrAfter=\"2010-06-01T13:03:00Z\" Recipient=\"http://saml.acs.url\"></SubjectConfirmationData></SubjectConfirmation></Subject><Conditions NotBefore=\"2010-06-01T12:59:55Z\" NotOnOrAfter=\"2010-06-01T16:00:00Z\"><AudienceRestriction><Audience>http://example.com</Audience></AudienceRestriction></Conditions><AuthnStatement AuthnInstant=\"2010-06-01T13:00:00Z\" SessionIndex=\"_abc\"><AuthnContext><AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef></AuthnContext></AuthnStatement><AttributeStatement><Attribute Name=\"emailAddress\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\" FriendlyName=\"emailAddress\"><AttributeValue>foo@example.com</AttributeValue></Attribute></AttributeStatement></Assertion>")
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe "with asserted_attributes_opt" do
|
236
|
+
let(:asserted_attributes_opt) {
|
237
|
+
{
|
238
|
+
'GivenName' => {
|
239
|
+
getter: :first_name
|
240
|
+
},
|
241
|
+
'SurName' => {
|
242
|
+
getter: -> (principal) {
|
243
|
+
principal.last_name
|
244
|
+
}
|
245
|
+
}
|
246
|
+
}
|
247
|
+
}
|
248
|
+
|
249
|
+
it "delegates asserted_attributes to opts" do
|
250
|
+
UserWithName = Struct.new(:email, :first_name, :last_name)
|
251
|
+
principal = UserWithName.new('foo@example.com', 'George', 'Washington')
|
252
|
+
builder = described_class.new(
|
253
|
+
reference_id,
|
254
|
+
issuer_uri,
|
255
|
+
principal,
|
256
|
+
audience_uri,
|
257
|
+
saml_request_id,
|
258
|
+
saml_acs_url,
|
259
|
+
algorithm,
|
260
|
+
authn_context_classref,
|
261
|
+
expiry,
|
262
|
+
encryption_opts,
|
263
|
+
session_expiry,
|
264
|
+
name_id_formats_opt,
|
265
|
+
asserted_attributes_opt
|
266
|
+
)
|
267
|
+
Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do
|
268
|
+
expect(builder.raw).to eq("<Assertion xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"_abc\" IssueInstant=\"2010-06-01T13:00:00Z\" Version=\"2.0\"><Issuer>http://sportngin.com</Issuer><Subject><NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">foo@example.com</NameID><SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><SubjectConfirmationData InResponseTo=\"123\" NotOnOrAfter=\"2010-06-01T13:03:00Z\" Recipient=\"http://saml.acs.url\"></SubjectConfirmationData></SubjectConfirmation></Subject><Conditions NotBefore=\"2010-06-01T12:59:55Z\" NotOnOrAfter=\"2010-06-01T16:00:00Z\"><AudienceRestriction><Audience>http://example.com</Audience></AudienceRestriction></Conditions><AuthnStatement AuthnInstant=\"2010-06-01T13:00:00Z\" SessionIndex=\"_abc\"><AuthnContext><AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef></AuthnContext></AuthnStatement><AttributeStatement><Attribute Name=\"GivenName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\" FriendlyName=\"GivenName\"><AttributeValue>George</AttributeValue></Attribute><Attribute Name=\"SurName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\" FriendlyName=\"SurName\"><AttributeValue>Washington</AttributeValue></Attribute></AttributeStatement></Assertion>")
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
202
272
|
end
|
203
273
|
end
|
@@ -17,6 +17,7 @@ module SamlIdp
|
|
17
17
|
it { should respond_to :attributes }
|
18
18
|
it { should respond_to :service_provider }
|
19
19
|
it { should respond_to :session_expiry }
|
20
|
+
it { should respond_to :logger }
|
20
21
|
|
21
22
|
it "has a valid x509_certificate" do
|
22
23
|
expect(subject.x509_certificate).to eq(Default::X509_CERTIFICATE)
|
@@ -1,7 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
module SamlIdp
|
3
3
|
describe Request do
|
4
|
-
let(:
|
4
|
+
let(:issuer) { 'localhost:3000' }
|
5
|
+
let(:raw_authn_request) do
|
6
|
+
"<samlp:AuthnRequest AssertionConsumerServiceURL='http://localhost:3000/saml/consume' Destination='http://localhost:1337/saml/auth' ID='_af43d1a0-e111-0130-661a-3c0754403fdb' IssueInstant='2013-08-06T22:01:35Z' Version='2.0' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol'><saml:Issuer xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>#{issuer}</saml:Issuer><samlp:NameIDPolicy AllowCreate='true' Format='urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol'/><samlp:RequestedAuthnContext Comparison='exact'><saml:AuthnContextClassRef xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></samlp:RequestedAuthnContext></samlp:AuthnRequest>"
|
7
|
+
end
|
5
8
|
|
6
9
|
describe "deflated request" do
|
7
10
|
let(:deflated_request) { Base64.encode64(Zlib::Deflate.deflate(raw_authn_request, 9)[2..-5]) }
|
@@ -57,16 +60,47 @@ module SamlIdp
|
|
57
60
|
expect(subject.request['ID']).to eq(subject.request_id)
|
58
61
|
end
|
59
62
|
|
60
|
-
it
|
61
|
-
expect(subject.requested_authn_context).to eq(
|
63
|
+
it 'has a valid authn context' do
|
64
|
+
expect(subject.requested_authn_context).to eq('urn:oasis:names:tc:SAML:2.0:ac:classes:Password')
|
62
65
|
end
|
63
66
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
context 'the issuer is empty' do
|
68
|
+
let(:issuer) { nil }
|
69
|
+
let(:logger) { ->(msg) { puts msg } }
|
70
|
+
|
71
|
+
before do
|
72
|
+
allow(SamlIdp.config).to receive(:logger).and_return(logger)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'is invalid' do
|
76
|
+
expect(subject.issuer).to_not eq('')
|
77
|
+
expect(subject.issuer).to be_nil
|
78
|
+
expect(subject.valid?).to eq(false)
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'a Ruby Logger is configured' do
|
82
|
+
let(:logger) { Logger.new($stdout) }
|
83
|
+
|
84
|
+
before do
|
85
|
+
allow(logger).to receive(:info)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'logs an error message' do
|
89
|
+
expect(subject.valid?).to be false
|
90
|
+
expect(logger).to have_received(:info).with('Unable to find service provider for issuer ')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'a logger lambda is configured' do
|
95
|
+
let(:logger) { double }
|
96
|
+
|
97
|
+
before { allow(logger).to receive(:call) }
|
98
|
+
|
99
|
+
it 'logs an error message' do
|
100
|
+
expect(subject.valid?).to be false
|
101
|
+
expect(logger).to have_received(:call).with('Unable to find service provider for issuer ')
|
102
|
+
end
|
103
|
+
end
|
70
104
|
end
|
71
105
|
end
|
72
106
|
|
@@ -26,6 +26,8 @@ module SamlIdp
|
|
26
26
|
end
|
27
27
|
let(:signed_response_opts) { true }
|
28
28
|
let(:unsigned_response_opts) { false }
|
29
|
+
let(:signed_assertion_opts) { true }
|
30
|
+
let(:compress_opts) { false }
|
29
31
|
let(:subject_encrypted) { described_class.new(reference_id,
|
30
32
|
response_id,
|
31
33
|
issuer_uri,
|
@@ -38,7 +40,11 @@ module SamlIdp
|
|
38
40
|
expiry,
|
39
41
|
encryption_opts,
|
40
42
|
session_expiry,
|
41
|
-
|
43
|
+
nil,
|
44
|
+
nil,
|
45
|
+
unsigned_response_opts,
|
46
|
+
signed_assertion_opts,
|
47
|
+
compress_opts
|
42
48
|
)
|
43
49
|
}
|
44
50
|
|
@@ -54,7 +60,11 @@ module SamlIdp
|
|
54
60
|
expiry,
|
55
61
|
nil,
|
56
62
|
session_expiry,
|
57
|
-
|
63
|
+
nil,
|
64
|
+
nil,
|
65
|
+
signed_response_opts,
|
66
|
+
signed_assertion_opts,
|
67
|
+
compress_opts
|
58
68
|
)
|
59
69
|
}
|
60
70
|
|
@@ -70,15 +80,97 @@ module SamlIdp
|
|
70
80
|
expect(subject.build).to be_present
|
71
81
|
end
|
72
82
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
83
|
+
context "encrypted" do
|
84
|
+
it "builds encrypted" do
|
85
|
+
expect(subject_encrypted.build).to_not match(audience_uri)
|
86
|
+
encoded_xml = subject_encrypted.build
|
87
|
+
resp_settings = saml_settings(saml_acs_url)
|
88
|
+
resp_settings.private_key = Default::SECRET_KEY
|
89
|
+
resp_settings.issuer = audience_uri
|
90
|
+
saml_resp = OneLogin::RubySaml::Response.new(encoded_xml, settings: resp_settings)
|
91
|
+
saml_resp.soft = false
|
92
|
+
expect(saml_resp.is_valid?).to eq(true)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "signed response" do
|
97
|
+
let(:resp_settings) do
|
98
|
+
resp_settings = saml_settings(saml_acs_url)
|
99
|
+
resp_settings.private_key = Default::SECRET_KEY
|
100
|
+
resp_settings.issuer = audience_uri
|
101
|
+
resp_settings
|
102
|
+
end
|
103
|
+
|
104
|
+
it "will build signed valid response" do
|
105
|
+
expect { subject.build }.not_to raise_error
|
106
|
+
signed_encoded_xml = subject.build
|
107
|
+
saml_resp = OneLogin::RubySaml::Response.new(signed_encoded_xml, settings: resp_settings)
|
108
|
+
expect(
|
109
|
+
Nokogiri::XML(saml_resp.response).at_xpath(
|
110
|
+
"//p:Response//ds:Signature",
|
111
|
+
{
|
112
|
+
"p" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
113
|
+
"ds" => "http://www.w3.org/2000/09/xmldsig#"
|
114
|
+
}
|
115
|
+
)).to be_present
|
116
|
+
expect(saml_resp.send(:validate_signature)).to eq(true)
|
117
|
+
expect(saml_resp.is_valid?).to eq(true)
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when signed_assertion_opts is true" do
|
121
|
+
it "builds a signed assertion" do
|
122
|
+
expect { subject.build }.not_to raise_error
|
123
|
+
signed_encoded_xml = subject.build
|
124
|
+
saml_resp = OneLogin::RubySaml::Response.new(signed_encoded_xml, settings: resp_settings)
|
125
|
+
expect(
|
126
|
+
Nokogiri::XML(saml_resp.response).at_xpath(
|
127
|
+
"//p:Response//a:Assertion//ds:Signature",
|
128
|
+
{
|
129
|
+
"p" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
130
|
+
"a" => "urn:oasis:names:tc:SAML:2.0:assertion",
|
131
|
+
"ds" => "http://www.w3.org/2000/09/xmldsig#"
|
132
|
+
}
|
133
|
+
)).to be_present
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "when signed_assertion_opts is false" do
|
138
|
+
let(:signed_assertion_opts) { false }
|
139
|
+
|
140
|
+
it "builds a raw assertion" do
|
141
|
+
expect { subject.build }.not_to raise_error
|
142
|
+
signed_encoded_xml = subject.build
|
143
|
+
saml_resp = OneLogin::RubySaml::Response.new(signed_encoded_xml, settings: resp_settings)
|
144
|
+
expect(
|
145
|
+
Nokogiri::XML(saml_resp.response).at_xpath(
|
146
|
+
"//p:Response//a:Assertion",
|
147
|
+
{
|
148
|
+
"p" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
149
|
+
"a" => "urn:oasis:names:tc:SAML:2.0:assertion"
|
150
|
+
}
|
151
|
+
)).to be_present
|
152
|
+
|
153
|
+
expect(
|
154
|
+
Nokogiri::XML(saml_resp.response).at_xpath(
|
155
|
+
"//p:Response//Assertion//ds:Signature",
|
156
|
+
{
|
157
|
+
"p" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
158
|
+
"ds" => "http://www.w3.org/2000/09/xmldsig#"
|
159
|
+
}
|
160
|
+
)).to_not be_present
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "when compress opts is true" do
|
165
|
+
let(:compress_opts) { true }
|
166
|
+
it "will build a compressed valid response" do
|
167
|
+
expect { subject.build }.not_to raise_error
|
168
|
+
compressed_signed_encoded_xml = subject.build
|
169
|
+
saml_resp = OneLogin::RubySaml::Response.new(compressed_signed_encoded_xml, settings: resp_settings)
|
170
|
+
expect(saml_resp.send(:validate_signature)).to eq(true)
|
171
|
+
expect(saml_resp.is_valid?).to eq(true)
|
172
|
+
end
|
173
|
+
end
|
82
174
|
end
|
83
175
|
|
84
176
|
it "will build signed valid response" do
|
@@ -1,48 +1,61 @@
|
|
1
1
|
class SamlIdpController < ApplicationController
|
2
|
-
|
2
|
+
include SamlIdp::Controller
|
3
3
|
|
4
|
+
if Rails::VERSION::MAJOR >= 4
|
5
|
+
before_action :add_view_path, only: [:new, :create, :logout]
|
4
6
|
before_action :validate_saml_request, only: [:new, :create, :logout]
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
else
|
8
|
+
before_filter :add_view_path, only: [:new, :create, :logout]
|
9
|
+
before_filter :validate_saml_request, only: [:new, :create, :logout]
|
10
|
+
end
|
11
|
+
|
12
|
+
def new
|
13
|
+
render template: "saml_idp/idp/new"
|
14
|
+
end
|
15
|
+
|
16
|
+
def show
|
17
|
+
render xml: SamlIdp.metadata.signed
|
18
|
+
end
|
19
|
+
|
20
|
+
def create
|
21
|
+
unless params[:email].blank? && params[:password].blank?
|
22
|
+
person = idp_authenticate(params[:email], params[:password])
|
23
|
+
if person.nil?
|
24
|
+
@saml_idp_fail_msg = "Incorrect email or password."
|
25
|
+
else
|
26
|
+
@saml_response = idp_make_saml_response(person)
|
27
|
+
render :template => "saml_idp/idp/saml_post", :layout => false
|
28
|
+
return
|
29
|
+
end
|
8
30
|
end
|
31
|
+
render :template => "saml_idp/idp/new"
|
32
|
+
end
|
9
33
|
|
10
|
-
|
11
|
-
|
12
|
-
|
34
|
+
def logout
|
35
|
+
idp_logout
|
36
|
+
@saml_response = idp_make_saml_response(nil)
|
37
|
+
render :template => "saml_idp/idp/saml_post", :layout => false
|
38
|
+
end
|
13
39
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@saml_idp_fail_msg = "Incorrect email or password."
|
19
|
-
else
|
20
|
-
@saml_response = idp_make_saml_response(person)
|
21
|
-
render :template => "saml_idp/idp/saml_post", :layout => false
|
22
|
-
return
|
23
|
-
end
|
24
|
-
end
|
25
|
-
render :template => "saml_idp/idp/new"
|
26
|
-
end
|
40
|
+
def idp_logout
|
41
|
+
raise NotImplementedError
|
42
|
+
end
|
43
|
+
private :idp_logout
|
27
44
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
45
|
+
def idp_authenticate(email, password)
|
46
|
+
{ :email => email }
|
47
|
+
end
|
48
|
+
protected :idp_authenticate
|
33
49
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
50
|
+
def idp_make_saml_response(person)
|
51
|
+
encode_response(person[:email])
|
52
|
+
end
|
53
|
+
protected :idp_make_saml_response
|
38
54
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
55
|
+
private
|
56
|
+
|
57
|
+
def add_view_path
|
58
|
+
prepend_view_path("app/views")
|
59
|
+
end
|
43
60
|
|
44
|
-
def idp_make_saml_response(person)
|
45
|
-
encode_response(person[:email])
|
46
|
-
end
|
47
|
-
protected :idp_make_saml_response
|
48
61
|
end
|
@@ -18,6 +18,7 @@ module RailsApp
|
|
18
18
|
|
19
19
|
# Custom directories with classes and modules you want to be autoloadable.
|
20
20
|
# config.autoload_paths += %W(#{config.root}/extras)
|
21
|
+
config.autoload_paths += %w[app/controllers]
|
21
22
|
|
22
23
|
# Only load the plugins named here, in the order given (default is alphabetical).
|
23
24
|
# :all can be used as a placeholder for all plugins not explicitly named.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saml_idp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Phenow
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -53,49 +53,49 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 1.6.2
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rexml
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0
|
61
|
+
version: '0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: xmlenc
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 0.7.1
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 0.7.1
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: activeresource
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '5.1'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '5.1'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: appraisal
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -109,33 +109,33 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: byebug
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: capybara
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
131
|
+
version: '2.16'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
138
|
+
version: '2.16'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: rails
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,49 +151,49 @@ dependencies:
|
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '5.2'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
154
|
+
name: rake
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
157
|
- - ">="
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version: '
|
159
|
+
version: '0'
|
160
160
|
type: :development
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
164
|
- - ">="
|
165
165
|
- !ruby/object:Gem::Version
|
166
|
-
version: '
|
166
|
+
version: '0'
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
|
-
name:
|
168
|
+
name: rspec
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
171
|
- - ">="
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version:
|
173
|
+
version: 3.7.0
|
174
174
|
type: :development
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - ">="
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version:
|
180
|
+
version: 3.7.0
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
|
-
name:
|
182
|
+
name: ruby-saml
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
184
184
|
requirements:
|
185
185
|
- - ">="
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version:
|
187
|
+
version: 1.7.2
|
188
188
|
type: :development
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
192
|
- - ">="
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
version:
|
194
|
+
version: 1.7.2
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
|
-
name:
|
196
|
+
name: simplecov
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
198
198
|
requirements:
|
199
199
|
- - ">="
|
@@ -207,19 +207,19 @@ dependencies:
|
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '0'
|
209
209
|
- !ruby/object:Gem::Dependency
|
210
|
-
name:
|
210
|
+
name: timecop
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
212
212
|
requirements:
|
213
213
|
- - ">="
|
214
214
|
- !ruby/object:Gem::Version
|
215
|
-
version: '0'
|
215
|
+
version: '0.8'
|
216
216
|
type: :development
|
217
217
|
prerelease: false
|
218
218
|
version_requirements: !ruby/object:Gem::Requirement
|
219
219
|
requirements:
|
220
220
|
- - ">="
|
221
221
|
- !ruby/object:Gem::Version
|
222
|
-
version: '0'
|
222
|
+
version: '0.8'
|
223
223
|
description: SAML IdP (Identity Provider) Library for Ruby
|
224
224
|
email: jon.phenow@sportngin.com
|
225
225
|
executables: []
|
@@ -365,22 +365,21 @@ metadata:
|
|
365
365
|
homepage_uri: https://github.com/saml-idp/saml_idp
|
366
366
|
source_code_uri: https://github.com/saml-idp/saml_idp
|
367
367
|
bug_tracker_uri: https://github.com/saml-idp/saml_idp/issues
|
368
|
-
documentation_uri: http://rdoc.info/gems/saml_idp/0.
|
369
|
-
post_install_message: |
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
If you just need to see the certificate `bundle open saml_idp` and go to
|
375
|
-
`lib/saml_idp/default.rb`
|
368
|
+
documentation_uri: http://rdoc.info/gems/saml_idp/0.15.0
|
369
|
+
post_install_message: |2
|
370
|
+
If you're just recently updating saml_idp - please be aware we've changed the default
|
371
|
+
certificate. See the PR and a description of why we've done this here:
|
372
|
+
https://github.com/saml-idp/saml_idp/pull/29
|
376
373
|
|
377
|
-
|
378
|
-
|
374
|
+
If you just need to see the certificate `bundle open saml_idp` and go to
|
375
|
+
`lib/saml_idp/default.rb`
|
379
376
|
|
380
|
-
|
377
|
+
Similarly, please see the README about certificates - you should avoid using the
|
378
|
+
defaults in a Production environment. Post any issues you to github.
|
381
379
|
|
382
|
-
|
383
|
-
|
380
|
+
** New in Version 0.3.0 **
|
381
|
+
Encrypted Assertions require the xmlenc gem. See the example in the Controller
|
382
|
+
section of the README.
|
384
383
|
rdoc_options:
|
385
384
|
- "--charset=UTF-8"
|
386
385
|
require_paths:
|
@@ -396,8 +395,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
396
395
|
- !ruby/object:Gem::Version
|
397
396
|
version: '0'
|
398
397
|
requirements: []
|
399
|
-
rubygems_version: 3.
|
400
|
-
signing_key:
|
398
|
+
rubygems_version: 3.3.7
|
399
|
+
signing_key:
|
401
400
|
specification_version: 4
|
402
401
|
summary: SAML Indentity Provider for Ruby
|
403
402
|
test_files:
|