saml_idp 0.6.0 → 0.7.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 +2 -1
- data/lib/saml_idp/assertion_builder.rb +16 -2
- data/lib/saml_idp/configurator.rb +2 -0
- data/lib/saml_idp/controller.rb +10 -2
- data/lib/saml_idp/saml_response.rb +6 -2
- data/lib/saml_idp/service_provider.rb +3 -2
- data/lib/saml_idp/version.rb +1 -1
- data/saml_idp.gemspec +0 -1
- data/spec/lib/saml_idp/.assertion_builder_spec.rb.swp +0 -0
- data/spec/lib/saml_idp/assertion_builder_spec.rb +24 -0
- data/spec/lib/saml_idp/configurator_spec.rb +5 -0
- data/spec/lib/saml_idp/saml_response_spec.rb +37 -2
- metadata +4 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 939a5fa00a7b08a69488c4e8c1b70d80134f5382
|
4
|
+
data.tar.gz: 74e7af28ec947ef5b89e346bade1d801920361ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4faba1443485f5eb1636fce1c0b6e24300530619eefc232f5d468cf093fec1b3db70427c6ec91fd9ceaead7ac59666322795fc98e2423cb4be3f914bf0646c7f
|
7
|
+
data.tar.gz: 153a2d258b1c5510e70999b4e76840d4b757894322ab5b2e990e2fa11610f4f31e6f9a661e5af3313f5aabd496a73623dfc79f85d392c054a9f63c2bc3af5b00
|
data/README.md
CHANGED
@@ -92,9 +92,10 @@ CERT
|
|
92
92
|
# config.organization_name = "Your Organization"
|
93
93
|
# config.organization_url = "http://example.com"
|
94
94
|
# config.base_saml_location = "#{base}/saml"
|
95
|
-
# config.reference_id_generator
|
95
|
+
# config.reference_id_generator # Default: -> { UUID.generate }
|
96
96
|
# config.attribute_service_location = "#{base}/saml/attributes"
|
97
97
|
# config.single_service_post_location = "#{base}/saml/auth"
|
98
|
+
# config.session_expiry = 86400 # Default: 0 which means never
|
98
99
|
|
99
100
|
# Principal (e.g. User) is passed in when you `encode_response`
|
100
101
|
#
|
@@ -15,10 +15,11 @@ module SamlIdp
|
|
15
15
|
attr_accessor :authn_context_classref
|
16
16
|
attr_accessor :expiry
|
17
17
|
attr_accessor :encryption_opts
|
18
|
+
attr_accessor :session_expiry
|
18
19
|
|
19
20
|
delegate :config, to: :SamlIdp
|
20
21
|
|
21
|
-
def initialize(reference_id, issuer_uri, principal, audience_uri, saml_request_id, saml_acs_url, raw_algorithm, authn_context_classref, expiry=60*60, encryption_opts=nil)
|
22
|
+
def initialize(reference_id, issuer_uri, principal, audience_uri, saml_request_id, saml_acs_url, raw_algorithm, authn_context_classref, expiry=60*60, encryption_opts=nil, session_expiry=nil)
|
22
23
|
self.reference_id = reference_id
|
23
24
|
self.issuer_uri = issuer_uri
|
24
25
|
self.principal = principal
|
@@ -29,6 +30,7 @@ module SamlIdp
|
|
29
30
|
self.authn_context_classref = authn_context_classref
|
30
31
|
self.expiry = expiry
|
31
32
|
self.encryption_opts = encryption_opts
|
33
|
+
self.session_expiry = session_expiry.nil? ? config.session_expiry : session_expiry
|
32
34
|
end
|
33
35
|
|
34
36
|
def fresh
|
@@ -55,7 +57,14 @@ module SamlIdp
|
|
55
57
|
restriction.Audience audience_uri
|
56
58
|
end
|
57
59
|
end
|
58
|
-
|
60
|
+
authn_statement_props = {
|
61
|
+
AuthnInstant: now_iso,
|
62
|
+
SessionIndex: reference_string,
|
63
|
+
}
|
64
|
+
unless session_expiry.zero?
|
65
|
+
authn_statement_props[:SessionNotOnOrAfter] = session_not_on_or_after
|
66
|
+
end
|
67
|
+
assertion.AuthnStatement authn_statement_props do |statement|
|
59
68
|
statement.AuthnContext do |context|
|
60
69
|
context.AuthnContextClassRef authn_context_classref
|
61
70
|
end
|
@@ -164,6 +173,11 @@ module SamlIdp
|
|
164
173
|
end
|
165
174
|
private :not_on_or_after_subject
|
166
175
|
|
176
|
+
def session_not_on_or_after
|
177
|
+
iso { now + session_expiry }
|
178
|
+
end
|
179
|
+
private :session_not_on_or_after
|
180
|
+
|
167
181
|
def iso
|
168
182
|
yield.iso8601
|
169
183
|
end
|
@@ -17,6 +17,7 @@ module SamlIdp
|
|
17
17
|
attr_accessor :single_logout_service_redirect_location
|
18
18
|
attr_accessor :attributes
|
19
19
|
attr_accessor :service_provider
|
20
|
+
attr_accessor :session_expiry
|
20
21
|
|
21
22
|
def initialize
|
22
23
|
self.x509_certificate = Default::X509_CERTIFICATE
|
@@ -27,6 +28,7 @@ module SamlIdp
|
|
27
28
|
self.service_provider.finder = ->(_) { Default::SERVICE_PROVIDER }
|
28
29
|
self.service_provider.metadata_persister = ->(id, settings) { }
|
29
30
|
self.service_provider.persisted_metadata_getter = ->(id, service_provider) { }
|
31
|
+
self.session_expiry = 0
|
30
32
|
self.attributes = {}
|
31
33
|
end
|
32
34
|
|
data/lib/saml_idp/controller.rb
CHANGED
@@ -35,7 +35,13 @@ module SamlIdp
|
|
35
35
|
|
36
36
|
def validate_saml_request(raw_saml_request = params[:SAMLRequest])
|
37
37
|
decode_request(raw_saml_request)
|
38
|
-
|
38
|
+
unless valid_saml_request?
|
39
|
+
if Rails::VERSION::MAJOR >= 4
|
40
|
+
head :forbidden
|
41
|
+
else
|
42
|
+
render nothing: true, status: :forbidden
|
43
|
+
end
|
44
|
+
end
|
39
45
|
end
|
40
46
|
|
41
47
|
def decode_request(raw_saml_request)
|
@@ -54,6 +60,7 @@ module SamlIdp
|
|
54
60
|
my_authn_context_classref = opts[:authn_context_classref] || authn_context_classref
|
55
61
|
acs_url = opts[:acs_url] || saml_acs_url
|
56
62
|
expiry = opts[:expiry] || 60*60
|
63
|
+
session_expiry = opts[:session_expiry]
|
57
64
|
encryption_opts = opts[:encryption] || nil
|
58
65
|
|
59
66
|
SamlResponse.new(
|
@@ -67,7 +74,8 @@ module SamlIdp
|
|
67
74
|
(opts[:algorithm] || algorithm || default_algorithm),
|
68
75
|
my_authn_context_classref,
|
69
76
|
expiry,
|
70
|
-
encryption_opts
|
77
|
+
encryption_opts,
|
78
|
+
session_expiry
|
71
79
|
).build
|
72
80
|
end
|
73
81
|
|
@@ -16,6 +16,7 @@ module SamlIdp
|
|
16
16
|
attr_accessor :authn_context_classref
|
17
17
|
attr_accessor :expiry
|
18
18
|
attr_accessor :encryption_opts
|
19
|
+
attr_accessor :session_expiry
|
19
20
|
|
20
21
|
def initialize(reference_id,
|
21
22
|
response_id,
|
@@ -27,7 +28,8 @@ module SamlIdp
|
|
27
28
|
algorithm,
|
28
29
|
authn_context_classref,
|
29
30
|
expiry=60*60,
|
30
|
-
encryption_opts=nil
|
31
|
+
encryption_opts=nil,
|
32
|
+
session_expiry=0
|
31
33
|
)
|
32
34
|
self.reference_id = reference_id
|
33
35
|
self.response_id = response_id
|
@@ -42,6 +44,7 @@ module SamlIdp
|
|
42
44
|
self.authn_context_classref = authn_context_classref
|
43
45
|
self.expiry = expiry
|
44
46
|
self.encryption_opts = encryption_opts
|
47
|
+
self.session_expiry = session_expiry
|
45
48
|
end
|
46
49
|
|
47
50
|
def build
|
@@ -72,7 +75,8 @@ module SamlIdp
|
|
72
75
|
algorithm,
|
73
76
|
authn_context_classref,
|
74
77
|
expiry,
|
75
|
-
encryption_opts
|
78
|
+
encryption_opts,
|
79
|
+
session_expiry
|
76
80
|
end
|
77
81
|
private :assertion_builder
|
78
82
|
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require '
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
2
3
|
require 'saml_idp/attributeable'
|
3
4
|
require 'saml_idp/incoming_metadata'
|
4
5
|
require 'saml_idp/persisted_metadata'
|
@@ -69,7 +70,7 @@ module SamlIdp
|
|
69
70
|
private :fresh_incoming_metadata
|
70
71
|
|
71
72
|
def request_metadata
|
72
|
-
metadata_url.present? ?
|
73
|
+
metadata_url.present? ? Net::HTTP.get(URI.parse(metadata_url)) : ""
|
73
74
|
end
|
74
75
|
private :request_metadata
|
75
76
|
end
|
data/lib/saml_idp/version.rb
CHANGED
data/saml_idp.gemspec
CHANGED
@@ -45,7 +45,6 @@ section of the README.
|
|
45
45
|
s.add_dependency('activesupport', '>= 3.2')
|
46
46
|
s.add_dependency('uuid', '~> 2.3')
|
47
47
|
s.add_dependency('builder', '~> 3.0')
|
48
|
-
s.add_dependency('httparty', '~> 0.14')
|
49
48
|
s.add_dependency('nokogiri', '>= 1.6.2')
|
50
49
|
|
51
50
|
s.add_development_dependency('rake', '~> 10.4.2')
|
Binary file
|
@@ -102,5 +102,29 @@ module SamlIdp
|
|
102
102
|
encrypted_xml = builder.encrypt
|
103
103
|
encrypted_xml.should_not match(audience_uri)
|
104
104
|
end
|
105
|
+
|
106
|
+
describe "with custom session_expiry configuration" do
|
107
|
+
let(:config) { SamlIdp::Configurator.new }
|
108
|
+
before do
|
109
|
+
config.session_expiry = 8
|
110
|
+
SamlIdp.stub(config: config)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "sets default session_expiry from config" do
|
114
|
+
builder = described_class.new(
|
115
|
+
reference_id,
|
116
|
+
issuer_uri,
|
117
|
+
name_id,
|
118
|
+
audience_uri,
|
119
|
+
saml_request_id,
|
120
|
+
saml_acs_url,
|
121
|
+
algorithm,
|
122
|
+
authn_context_classref,
|
123
|
+
expiry,
|
124
|
+
encryption_opts
|
125
|
+
)
|
126
|
+
builder.session_expiry.should == 8
|
127
|
+
end
|
128
|
+
end
|
105
129
|
end
|
106
130
|
end
|
@@ -15,6 +15,7 @@ module SamlIdp
|
|
15
15
|
it { should respond_to :name_id }
|
16
16
|
it { should respond_to :attributes }
|
17
17
|
it { should respond_to :service_provider }
|
18
|
+
it { should respond_to :session_expiry }
|
18
19
|
|
19
20
|
it "has a valid x509_certificate" do
|
20
21
|
subject.x509_certificate.should == Default::X509_CERTIFICATE
|
@@ -40,5 +41,9 @@ module SamlIdp
|
|
40
41
|
it "can call service provider metadata persister" do
|
41
42
|
subject.service_provider.metadata_persister.should respond_to :call
|
42
43
|
end
|
44
|
+
|
45
|
+
it 'has a valid session_expiry' do
|
46
|
+
subject.session_expiry.should == 0
|
47
|
+
end
|
43
48
|
end
|
44
49
|
end
|
@@ -16,6 +16,7 @@ module SamlIdp
|
|
16
16
|
Saml::XML::Namespaces::AuthnContext::ClassRef::PASSWORD
|
17
17
|
}
|
18
18
|
let(:expiry) { 3 * 60 * 60 }
|
19
|
+
let(:session_expiry) { 24 * 60 * 60 }
|
19
20
|
let (:encryption_opts) do
|
20
21
|
{
|
21
22
|
cert: Default::X509_CERTIFICATE,
|
@@ -33,7 +34,8 @@ module SamlIdp
|
|
33
34
|
algorithm,
|
34
35
|
authn_context_classref,
|
35
36
|
expiry,
|
36
|
-
encryption_opts
|
37
|
+
encryption_opts,
|
38
|
+
session_expiry
|
37
39
|
)
|
38
40
|
}
|
39
41
|
|
@@ -46,10 +48,20 @@ module SamlIdp
|
|
46
48
|
saml_acs_url,
|
47
49
|
algorithm,
|
48
50
|
authn_context_classref,
|
49
|
-
expiry
|
51
|
+
expiry,
|
52
|
+
nil,
|
53
|
+
session_expiry
|
50
54
|
)
|
51
55
|
}
|
52
56
|
|
57
|
+
before do
|
58
|
+
Timecop.freeze(Time.local(1990, "jan", 1))
|
59
|
+
end
|
60
|
+
|
61
|
+
after do
|
62
|
+
Timecop.return
|
63
|
+
end
|
64
|
+
|
53
65
|
it "has a valid build" do
|
54
66
|
subject.build.should be_present
|
55
67
|
end
|
@@ -64,5 +76,28 @@ module SamlIdp
|
|
64
76
|
saml_resp.soft = false
|
65
77
|
saml_resp.is_valid?.should == true
|
66
78
|
end
|
79
|
+
|
80
|
+
it "sets session expiration" do
|
81
|
+
saml_resp = OneLogin::RubySaml::Response.new(subject.build)
|
82
|
+
saml_resp.session_expires_at.should == Time.local(1990, "jan", 2).iso8601
|
83
|
+
end
|
84
|
+
|
85
|
+
context "session expiration is set to 0" do
|
86
|
+
let(:session_expiry) { 0 }
|
87
|
+
|
88
|
+
it "builds a valid request" do
|
89
|
+
resp_settings = saml_settings(saml_acs_url)
|
90
|
+
resp_settings.issuer = audience_uri
|
91
|
+
saml_resp = OneLogin::RubySaml::Response.new(subject.build, settings: resp_settings)
|
92
|
+
saml_resp.is_valid?.should == true
|
93
|
+
end
|
94
|
+
|
95
|
+
it "doesn't set a session expiration" do
|
96
|
+
resp_settings = saml_settings(saml_acs_url)
|
97
|
+
resp_settings.issuer = audience_uri
|
98
|
+
saml_resp = OneLogin::RubySaml::Response.new(subject.build, settings: resp_settings)
|
99
|
+
saml_resp.session_expires_at.should be_nil
|
100
|
+
end
|
101
|
+
end
|
67
102
|
end
|
68
103
|
end
|
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.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Phenow
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -52,20 +52,6 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: httparty
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0.14'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0.14'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: nokogiri
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -234,6 +220,7 @@ files:
|
|
234
220
|
- saml_idp.gemspec
|
235
221
|
- spec/acceptance/acceptance_helper.rb
|
236
222
|
- spec/acceptance/idp_controller_spec.rb
|
223
|
+
- spec/lib/saml_idp/.assertion_builder_spec.rb.swp
|
237
224
|
- spec/lib/saml_idp/algorithmable_spec.rb
|
238
225
|
- spec/lib/saml_idp/assertion_builder_spec.rb
|
239
226
|
- spec/lib/saml_idp/attribute_decorator_spec.rb
|
@@ -367,6 +354,7 @@ summary: SAML Indentity Provider in ruby
|
|
367
354
|
test_files:
|
368
355
|
- spec/acceptance/acceptance_helper.rb
|
369
356
|
- spec/acceptance/idp_controller_spec.rb
|
357
|
+
- spec/lib/saml_idp/.assertion_builder_spec.rb.swp
|
370
358
|
- spec/lib/saml_idp/algorithmable_spec.rb
|
371
359
|
- spec/lib/saml_idp/assertion_builder_spec.rb
|
372
360
|
- spec/lib/saml_idp/attribute_decorator_spec.rb
|