casino_core 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/VERSION +1 -1
- data/casino_core.gemspec +5 -1
- data/lib/casino_core/helper/proxy_granting_tickets.rb +1 -1
- data/lib/casino_core/model/service_ticket.rb +1 -1
- data/lib/casino_core/model/service_ticket/single_sign_out_notifier.rb +8 -3
- data/spec/model/service_ticket/single_sign_out_notifier_spec.rb +55 -0
- data/spec/model/service_ticket_spec.rb +16 -0
- data/spec/processor/session_destroyer_spec.rb +0 -13
- data/spec/processor/ticket_validator_spec.rb +37 -2
- data/spec/spec_helper.rb +3 -1
- metadata +14 -2
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -27,6 +27,7 @@ GEM
|
|
27
27
|
rdoc
|
28
28
|
json (1.7.5)
|
29
29
|
multi_json (1.5.0)
|
30
|
+
nokogiri (1.5.6)
|
30
31
|
rake (10.0.3)
|
31
32
|
rdoc (3.12)
|
32
33
|
json (~> 1.4)
|
@@ -60,6 +61,7 @@ DEPENDENCIES
|
|
60
61
|
bundler (~> 1.2.0)
|
61
62
|
database_cleaner
|
62
63
|
jeweler (~> 1.8.4)
|
64
|
+
nokogiri
|
63
65
|
redcarpet
|
64
66
|
rspec (~> 2.12.0)
|
65
67
|
simplecov (~> 0.7.1)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.3
|
data/casino_core.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "casino_core"
|
8
|
-
s.version = "1.0.
|
8
|
+
s.version = "1.0.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Nils Caspar"]
|
@@ -89,6 +89,7 @@ Gem::Specification.new do |s|
|
|
89
89
|
"spec/authenticator/static_spec.rb",
|
90
90
|
"spec/model/login_ticket_spec.rb",
|
91
91
|
"spec/model/proxy_ticket_spec.rb",
|
92
|
+
"spec/model/service_ticket/single_sign_out_notifier_spec.rb",
|
92
93
|
"spec/model/service_ticket_spec.rb",
|
93
94
|
"spec/model/ticket_granting_ticket_spec.rb",
|
94
95
|
"spec/processor/legacy_validator_spec.rb",
|
@@ -124,6 +125,7 @@ Gem::Specification.new do |s|
|
|
124
125
|
s.add_development_dependency(%q<sqlite3>, [">= 0"])
|
125
126
|
s.add_development_dependency(%q<database_cleaner>, [">= 0"])
|
126
127
|
s.add_development_dependency(%q<webmock>, [">= 0"])
|
128
|
+
s.add_development_dependency(%q<nokogiri>, [">= 0"])
|
127
129
|
else
|
128
130
|
s.add_dependency(%q<activerecord>, ["~> 3.2.9"])
|
129
131
|
s.add_dependency(%q<addressable>, ["~> 2.3.2"])
|
@@ -137,6 +139,7 @@ Gem::Specification.new do |s|
|
|
137
139
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
138
140
|
s.add_dependency(%q<database_cleaner>, [">= 0"])
|
139
141
|
s.add_dependency(%q<webmock>, [">= 0"])
|
142
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
140
143
|
end
|
141
144
|
else
|
142
145
|
s.add_dependency(%q<activerecord>, ["~> 3.2.9"])
|
@@ -151,6 +154,7 @@ Gem::Specification.new do |s|
|
|
151
154
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
152
155
|
s.add_dependency(%q<database_cleaner>, [">= 0"])
|
153
156
|
s.add_dependency(%q<webmock>, [">= 0"])
|
157
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
154
158
|
end
|
155
159
|
end
|
156
160
|
|
@@ -13,7 +13,7 @@ module CASinoCore
|
|
13
13
|
def acquire_proxy_granting_ticket(pgt_url, service_ticket)
|
14
14
|
begin
|
15
15
|
return contact_callback_server(pgt_url, service_ticket)
|
16
|
-
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError
|
16
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
17
17
|
logger.warn "Exception while communicating with proxy-granting ticket callback server: #{e.message}"
|
18
18
|
end
|
19
19
|
nil
|
@@ -16,7 +16,7 @@ class CASinoCore::Model::ServiceTicket < ActiveRecord::Base
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.cleanup_consumed
|
19
|
-
self.destroy_all(['created_at < ? AND consumed = ?', CASinoCore::Settings.service_ticket[:lifetime_consumed].seconds.ago, true])
|
19
|
+
self.destroy_all(['(ticket_granting_ticket_id IS NULL OR created_at < ?) AND consumed = ?', CASinoCore::Settings.service_ticket[:lifetime_consumed].seconds.ago, true])
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.cleanup_consumed_hard
|
@@ -20,8 +20,13 @@ class CASinoCore::Model::ServiceTicket::SingleSignOutNotifier
|
|
20
20
|
private
|
21
21
|
def build_xml
|
22
22
|
xml = Builder::XmlMarkup.new(indent: 2)
|
23
|
-
xml.samlp :LogoutRequest,
|
24
|
-
|
23
|
+
xml.samlp :LogoutRequest,
|
24
|
+
'xmlns:samlp' => 'urn:oasis:names:tc:SAML:2.0:protocol',
|
25
|
+
'xmlns:saml' => 'urn:oasis:names:tc:SAML:2.0:assertion',
|
26
|
+
ID: SecureRandom.uuid,
|
27
|
+
Version: '2.0',
|
28
|
+
IssueInstant: Time.now do |logout_request|
|
29
|
+
logout_request.saml :NameID, '@NOT_USED@'
|
25
30
|
logout_request.samlp :SessionIndex, @service_ticket.ticket
|
26
31
|
end
|
27
32
|
xml.target!
|
@@ -49,7 +54,7 @@ class CASinoCore::Model::ServiceTicket::SingleSignOutNotifier
|
|
49
54
|
return false
|
50
55
|
end
|
51
56
|
end
|
52
|
-
rescue
|
57
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
53
58
|
logger.warn "Failed to send logout notification to service #{uri} due to #{e}"
|
54
59
|
return false
|
55
60
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
describe CASinoCore::Model::ServiceTicket::SingleSignOutNotifier do
|
5
|
+
let(:ticket) { 'ST-123456' }
|
6
|
+
let(:service) { 'http://www.example.org/' }
|
7
|
+
let(:service_ticket) { CASinoCore::Model::ServiceTicket.create ticket: ticket, service: service }
|
8
|
+
let(:notifier) { described_class.new service_ticket }
|
9
|
+
|
10
|
+
describe '#notify' do
|
11
|
+
before(:each) do
|
12
|
+
stub_request(:post, service)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'sends a valid Single Sign Out XML to the service URL' do
|
16
|
+
notifier.notify
|
17
|
+
WebMock.should have_requested(:post, service).with { |request|
|
18
|
+
post_params = CGI.parse(request.body)
|
19
|
+
post_params.should_not be_nil
|
20
|
+
xml = Nokogiri::XML post_params['logoutRequest'].first
|
21
|
+
xml.at_xpath('/samlp:LogoutRequest/samlp:SessionIndex').text.strip.should == service_ticket.ticket
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when it is a success' do
|
26
|
+
it 'returns true' do
|
27
|
+
notifier.notify.should == true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with server error' do
|
32
|
+
[404, 500].each do |status_code|
|
33
|
+
context "#{status_code}" do
|
34
|
+
before(:each) do
|
35
|
+
stub_request(:post, service).to_return status: status_code
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns false' do
|
39
|
+
notifier.notify.should == false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'connection timeout' do
|
45
|
+
before(:each) do
|
46
|
+
stub_request(:post, service).to_raise Timeout::Error
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns false' do
|
50
|
+
notifier.notify.should == false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -38,6 +38,22 @@ describe CASinoCore::Model::ServiceTicket do
|
|
38
38
|
end.should change(described_class, :count).by(-1)
|
39
39
|
described_class.find_by_ticket('ST-12345').should be_false
|
40
40
|
end
|
41
|
+
|
42
|
+
it 'deletes consumed service tickets without ticket_granting_ticket' do
|
43
|
+
consumed_ticket.ticket_granting_ticket_id = nil
|
44
|
+
consumed_ticket.save!
|
45
|
+
lambda do
|
46
|
+
described_class.cleanup_consumed
|
47
|
+
end.should change(described_class, :count).by(-1)
|
48
|
+
described_class.find_by_ticket('ST-12345').should be_false
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'does not delete unexpired service tickets' do
|
52
|
+
consumed_ticket # create the ticket
|
53
|
+
lambda do
|
54
|
+
described_class.cleanup_consumed
|
55
|
+
end.should_not change(described_class, :count)
|
56
|
+
end
|
41
57
|
end
|
42
58
|
|
43
59
|
describe '#destroy' do
|
@@ -57,19 +57,6 @@ describe CASinoCore::Processor::SessionDestroyer do
|
|
57
57
|
listener.should_receive(:ticket_deleted).with(no_args)
|
58
58
|
processor.process(params, cookies, user_agent)
|
59
59
|
end
|
60
|
-
|
61
|
-
it 'deletes the dependent service ticket' do
|
62
|
-
service_ticket.ticket # creates the service ticket
|
63
|
-
lambda {
|
64
|
-
processor.process(params, cookies, user_agent)
|
65
|
-
}.should change(CASinoCore::Model::ServiceTicket, :count).by(-1)
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'nullifies the dependent service ticket if destroying fails' do
|
69
|
-
lambda {
|
70
|
-
processor.process(params, cookies, user_agent)
|
71
|
-
}.should change { consumed_service_ticket.reload.ticket_granting_ticket_id }.to(nil)
|
72
|
-
end
|
73
60
|
end
|
74
61
|
|
75
62
|
context 'with an invalid ticket-granting ticket' do
|
@@ -83,10 +83,11 @@ require 'spec_helper'
|
|
83
83
|
end
|
84
84
|
|
85
85
|
context 'with proxy-granting ticket callback server' do
|
86
|
-
let(:
|
86
|
+
let(:pgt_url) { 'https://www.example.org' }
|
87
|
+
let(:parameters_with_pgt_url) { parameters.merge pgtUrl: pgt_url }
|
87
88
|
|
88
89
|
before(:each) do
|
89
|
-
stub_request(:get,
|
90
|
+
stub_request(:get, /#{pgt_url}\/\?pgtId=[^&]+&pgtIou=[^&]+/)
|
90
91
|
end
|
91
92
|
|
92
93
|
it 'calls the #validation_succeeded method on the listener' do
|
@@ -113,6 +114,40 @@ require 'spec_helper'
|
|
113
114
|
pgtIou: proxy_granting_ticket.iou
|
114
115
|
})
|
115
116
|
end
|
117
|
+
|
118
|
+
context 'when callback server gives an error' do
|
119
|
+
before(:each) do
|
120
|
+
stub_request(:get, /#{pgt_url}.*/).to_return status: 404
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'calls the #validation_succeeded method on the listener' do
|
124
|
+
listener.should_receive(:validation_succeeded).with(regex_success)
|
125
|
+
processor.process(parameters_with_pgt_url)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'does not create a proxy-granting ticket' do
|
129
|
+
lambda do
|
130
|
+
processor.process(parameters_with_pgt_url)
|
131
|
+
end.should_not change(service_ticket.proxy_granting_tickets, :count)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when callback server is unreachable' do
|
136
|
+
before(:each) do
|
137
|
+
stub_request(:get, /#{pgt_url}.*/).to_raise(Timeout::Error)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'calls the #validation_succeeded method on the listener' do
|
141
|
+
listener.should_receive(:validation_succeeded).with(regex_success)
|
142
|
+
processor.process(parameters_with_pgt_url)
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'does not create a proxy-granting ticket' do
|
146
|
+
lambda do
|
147
|
+
processor.process(parameters_with_pgt_url)
|
148
|
+
end.should_not change(service_ticket.proxy_granting_tickets, :count)
|
149
|
+
end
|
150
|
+
end
|
116
151
|
end
|
117
152
|
end
|
118
153
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: casino_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.0.
|
5
|
+
version: 1.0.3
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Nils Caspar
|
@@ -144,6 +144,17 @@ dependencies:
|
|
144
144
|
type: :development
|
145
145
|
prerelease: false
|
146
146
|
version_requirements: *id012
|
147
|
+
- !ruby/object:Gem::Dependency
|
148
|
+
name: nokogiri
|
149
|
+
requirement: &id013 !ruby/object:Gem::Requirement
|
150
|
+
none: false
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: "0"
|
155
|
+
type: :development
|
156
|
+
prerelease: false
|
157
|
+
version_requirements: *id013
|
147
158
|
description: A CAS server core library.
|
148
159
|
email: ncaspar@me.com
|
149
160
|
executables: []
|
@@ -226,6 +237,7 @@ files:
|
|
226
237
|
- spec/authenticator/static_spec.rb
|
227
238
|
- spec/model/login_ticket_spec.rb
|
228
239
|
- spec/model/proxy_ticket_spec.rb
|
240
|
+
- spec/model/service_ticket/single_sign_out_notifier_spec.rb
|
229
241
|
- spec/model/service_ticket_spec.rb
|
230
242
|
- spec/model/ticket_granting_ticket_spec.rb
|
231
243
|
- spec/processor/legacy_validator_spec.rb
|
@@ -251,7 +263,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
251
263
|
requirements:
|
252
264
|
- - ">="
|
253
265
|
- !ruby/object:Gem::Version
|
254
|
-
hash:
|
266
|
+
hash: 1358580775161495326
|
255
267
|
segments:
|
256
268
|
- 0
|
257
269
|
version: "0"
|