casino_core 1.0.3 → 1.0.4
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.
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -0
- data/VERSION +1 -1
- data/casino_core.gemspec +12 -3
- data/config/cas.yml +10 -11
- data/db/migrate/20121231114141_add_authenticator_to_ticket_granting_tickets.rb +15 -0
- data/db/schema.rb +3 -2
- data/lib/casino_core/builder/ticket_validation_response.rb +0 -2
- data/lib/casino_core/model/ticket_granting_ticket.rb +2 -2
- data/lib/casino_core/processor/login_credential_acceptor.rb +11 -12
- data/lib/casino_core/processor/login_credential_requestor.rb +7 -2
- data/lib/casino_core/processor/session_overview.rb +4 -1
- data/lib/casino_core/settings.rb +3 -3
- data/spec/model/service_ticket/single_sign_out_notifier_spec.rb +3 -4
- data/spec/model/ticket_granting_ticket_spec.rb +6 -13
- data/spec/processor/legacy_validator_spec.rb +2 -12
- data/spec/processor/login_credential_acceptor_spec.rb +10 -1
- data/spec/processor/login_credential_requestor_spec.rb +26 -10
- data/spec/processor/logout_spec.rb +2 -9
- data/spec/processor/proxy_ticket_provider_spec.rb +1 -10
- data/spec/processor/proxy_ticket_validator_spec.rb +13 -14
- data/spec/processor/session_destroyer_spec.rb +6 -34
- data/spec/processor/session_overview_spec.rb +15 -17
- data/spec/processor/ticket_validator_spec.rb +16 -14
- data/spec/spec_helper.rb +11 -0
- data/spec/support/factories/login_ticket_factory.rb +16 -0
- data/spec/support/factories/proxy_granting_ticket_factory.rb +16 -0
- data/spec/support/factories/proxy_ticket_factory.rb +17 -0
- data/spec/support/factories/service_ticket_factory.rb +17 -0
- data/spec/support/factories/ticket_granting_ticket_factory.rb +13 -0
- metadata +20 -3
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -18,6 +18,8 @@ GEM
|
|
18
18
|
crack (0.3.1)
|
19
19
|
database_cleaner (0.9.1)
|
20
20
|
diff-lcs (1.1.3)
|
21
|
+
factory_girl (4.1.0)
|
22
|
+
activesupport (>= 3.0.0)
|
21
23
|
git (1.2.5)
|
22
24
|
i18n (0.6.1)
|
23
25
|
jeweler (1.8.4)
|
@@ -60,6 +62,7 @@ DEPENDENCIES
|
|
60
62
|
addressable (~> 2.3.2)
|
61
63
|
bundler (~> 1.2.0)
|
62
64
|
database_cleaner
|
65
|
+
factory_girl (~> 4.1.0)
|
63
66
|
jeweler (~> 1.8.4)
|
64
67
|
nokogiri
|
65
68
|
redcarpet
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.4
|
data/casino_core.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
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.4"
|
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"]
|
12
|
-
s.date = "2012-12-
|
12
|
+
s.date = "2012-12-30"
|
13
13
|
s.description = "A CAS server core library."
|
14
14
|
s.email = "ncaspar@me.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -48,6 +48,7 @@ Gem::Specification.new do |s|
|
|
48
48
|
"db/migrate/20121225231713_no_default_granter_type.rb",
|
49
49
|
"db/migrate/20121226192211_fix_index_for_granter_on_proxy_granting_ticket.rb",
|
50
50
|
"db/migrate/20121226211511_allow_service_tickets_without_ticket_granting_ticket.rb",
|
51
|
+
"db/migrate/20121231114141_add_authenticator_to_ticket_granting_tickets.rb",
|
51
52
|
"db/schema.rb",
|
52
53
|
"lib/casino_core.rb",
|
53
54
|
"lib/casino_core/authenticator.rb",
|
@@ -101,7 +102,12 @@ Gem::Specification.new do |s|
|
|
101
102
|
"spec/processor/session_destroyer_spec.rb",
|
102
103
|
"spec/processor/session_overview_spec.rb",
|
103
104
|
"spec/processor/ticket_validator_spec.rb",
|
104
|
-
"spec/spec_helper.rb"
|
105
|
+
"spec/spec_helper.rb",
|
106
|
+
"spec/support/factories/login_ticket_factory.rb",
|
107
|
+
"spec/support/factories/proxy_granting_ticket_factory.rb",
|
108
|
+
"spec/support/factories/proxy_ticket_factory.rb",
|
109
|
+
"spec/support/factories/service_ticket_factory.rb",
|
110
|
+
"spec/support/factories/ticket_granting_ticket_factory.rb"
|
105
111
|
]
|
106
112
|
s.homepage = "http://github.com/pencil/CASinoCore"
|
107
113
|
s.licenses = ["MIT"]
|
@@ -126,6 +132,7 @@ Gem::Specification.new do |s|
|
|
126
132
|
s.add_development_dependency(%q<database_cleaner>, [">= 0"])
|
127
133
|
s.add_development_dependency(%q<webmock>, [">= 0"])
|
128
134
|
s.add_development_dependency(%q<nokogiri>, [">= 0"])
|
135
|
+
s.add_development_dependency(%q<factory_girl>, ["~> 4.1.0"])
|
129
136
|
else
|
130
137
|
s.add_dependency(%q<activerecord>, ["~> 3.2.9"])
|
131
138
|
s.add_dependency(%q<addressable>, ["~> 2.3.2"])
|
@@ -140,6 +147,7 @@ Gem::Specification.new do |s|
|
|
140
147
|
s.add_dependency(%q<database_cleaner>, [">= 0"])
|
141
148
|
s.add_dependency(%q<webmock>, [">= 0"])
|
142
149
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
150
|
+
s.add_dependency(%q<factory_girl>, ["~> 4.1.0"])
|
143
151
|
end
|
144
152
|
else
|
145
153
|
s.add_dependency(%q<activerecord>, ["~> 3.2.9"])
|
@@ -155,6 +163,7 @@ Gem::Specification.new do |s|
|
|
155
163
|
s.add_dependency(%q<database_cleaner>, [">= 0"])
|
156
164
|
s.add_dependency(%q<webmock>, [">= 0"])
|
157
165
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
166
|
+
s.add_dependency(%q<factory_girl>, ["~> 4.1.0"])
|
158
167
|
end
|
159
168
|
end
|
160
169
|
|
data/config/cas.yml
CHANGED
@@ -7,25 +7,24 @@ defaults: &defaults
|
|
7
7
|
proxy_ticket:
|
8
8
|
lifetime_unconsumed: 300
|
9
9
|
lifetime_consumed: 86400
|
10
|
-
|
11
|
-
development:
|
12
|
-
<<: *defaults
|
13
10
|
authenticators:
|
14
|
-
|
11
|
+
static_1:
|
15
12
|
class: "CASinoCore::Authenticator::Static"
|
16
13
|
options:
|
17
14
|
users:
|
18
15
|
testuser:
|
19
16
|
password: "foobar123"
|
20
17
|
name: "Test User"
|
21
|
-
|
22
|
-
test:
|
23
|
-
<<: *defaults
|
24
|
-
authenticators:
|
25
|
-
-
|
18
|
+
static_2:
|
26
19
|
class: "CASinoCore::Authenticator::Static"
|
27
20
|
options:
|
28
21
|
users:
|
29
|
-
|
30
|
-
password: "
|
22
|
+
example:
|
23
|
+
password: "dito123"
|
31
24
|
name: "Test User"
|
25
|
+
|
26
|
+
development:
|
27
|
+
<<: *defaults
|
28
|
+
|
29
|
+
test:
|
30
|
+
<<: *defaults
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class AddAuthenticatorToTicketGrantingTickets < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
add_column :ticket_granting_tickets, :authenticator, :string, null: true
|
4
|
+
CASinoCore::Model::TicketGrantingTicket.delete_all
|
5
|
+
change_column :ticket_granting_tickets, :authenticator, :string, null: false
|
6
|
+
add_index :ticket_granting_tickets, [:authenticator, :username]
|
7
|
+
remove_index :ticket_granting_tickets, :username
|
8
|
+
end
|
9
|
+
|
10
|
+
def down
|
11
|
+
remove_index :ticket_granting_tickets, [:authenticator, :username]
|
12
|
+
remove_column :ticket_granting_tickets, :authenticator
|
13
|
+
add_index :ticket_granting_tickets, :username
|
14
|
+
end
|
15
|
+
end
|
data/db/schema.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended to check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(:version =>
|
14
|
+
ActiveRecord::Schema.define(:version => 20121231114141) do
|
15
15
|
|
16
16
|
create_table "login_tickets", :force => true do |t|
|
17
17
|
t.string "ticket", :null => false
|
@@ -67,9 +67,10 @@ ActiveRecord::Schema.define(:version => 20121226211511) do
|
|
67
67
|
t.datetime "created_at", :null => false
|
68
68
|
t.datetime "updated_at", :null => false
|
69
69
|
t.string "user_agent"
|
70
|
+
t.string "authenticator", :null => false
|
70
71
|
end
|
71
72
|
|
73
|
+
add_index "ticket_granting_tickets", ["authenticator", "username"], :name => "index_ticket_granting_tickets_on_authenticator_and_username"
|
72
74
|
add_index "ticket_granting_tickets", ["ticket"], :name => "index_ticket_granting_tickets_on_ticket", :unique => true
|
73
|
-
add_index "ticket_granting_tickets", ["username"], :name => "index_ticket_granting_tickets_on_username"
|
74
75
|
|
75
76
|
end
|
@@ -37,8 +37,6 @@ class CASinoCore::Builder::TicketValidationResponse < CASinoCore::Builder
|
|
37
37
|
def serialize_extra_attribute(builder, key, value)
|
38
38
|
if value.kind_of?(String) || value.kind_of?(Numeric) || value.kind_of?(Symbol)
|
39
39
|
builder.cas key, "#{value}"
|
40
|
-
elsif value.kind_of?(Numeric)
|
41
|
-
builder.cas key, value.to_s
|
42
40
|
else
|
43
41
|
builder.cas key do |container|
|
44
42
|
container.cdata! value.to_yaml
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'casino_core/model'
|
2
2
|
|
3
3
|
class CASinoCore::Model::TicketGrantingTicket < ActiveRecord::Base
|
4
|
-
attr_accessible :ticket, :username, :user_agent, :extra_attributes
|
4
|
+
attr_accessible :ticket, :authenticator, :username, :user_agent, :extra_attributes
|
5
5
|
serialize :extra_attributes, Hash
|
6
6
|
validates :ticket, uniqueness: true
|
7
7
|
has_many :service_tickets
|
@@ -18,7 +18,7 @@ class CASinoCore::Model::TicketGrantingTicket < ActiveRecord::Base
|
|
18
18
|
if other_ticket.nil?
|
19
19
|
false
|
20
20
|
else
|
21
|
-
other_ticket.username == self.username
|
21
|
+
other_ticket.username == self.username && other_ticket.authenticator == self.authenticator
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -23,9 +23,9 @@ class CASinoCore::Processor::LoginCredentialAcceptor < CASinoCore::Processor
|
|
23
23
|
params ||= {}
|
24
24
|
cookies ||= {}
|
25
25
|
if login_ticket_valid?(params[:lt])
|
26
|
-
|
27
|
-
if !
|
28
|
-
ticket_granting_ticket = acquire_ticket_granting_ticket(
|
26
|
+
authentication_result = validate_login_credentials(params[:username], params[:password])
|
27
|
+
if !authentication_result.nil?
|
28
|
+
ticket_granting_ticket = acquire_ticket_granting_ticket(authentication_result, user_agent)
|
29
29
|
url = unless params[:service].nil?
|
30
30
|
acquire_service_ticket(ticket_granting_ticket, params[:service], true).service_with_ticket_url
|
31
31
|
end
|
@@ -55,24 +55,23 @@ class CASinoCore::Processor::LoginCredentialAcceptor < CASinoCore::Processor
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def validate_login_credentials(username, password)
|
58
|
-
|
59
|
-
CASinoCore::Settings.authenticators.each do |authenticator|
|
58
|
+
authentication_result = nil
|
59
|
+
CASinoCore::Settings.authenticators.each do |authenticator_name, authenticator|
|
60
60
|
data = authenticator.validate(username, password)
|
61
61
|
if data
|
62
|
-
|
63
|
-
|
64
|
-
end
|
65
|
-
user_data = data
|
66
|
-
logger.info("Credentials for username '#{data[:username]}' successfully validated using #{authenticator.class}")
|
62
|
+
authentication_result = { authenticator: authenticator_name, user_data: data }
|
63
|
+
logger.info("Credentials for username '#{data[:username]}' successfully validated using authenticator '#{authenticator_name}' (#{authenticator.class})")
|
67
64
|
break
|
68
65
|
end
|
69
66
|
end
|
70
|
-
|
67
|
+
authentication_result
|
71
68
|
end
|
72
69
|
|
73
|
-
def acquire_ticket_granting_ticket(
|
70
|
+
def acquire_ticket_granting_ticket(authentication_result, user_agent = nil)
|
71
|
+
user_data = authentication_result[:user_data]
|
74
72
|
CASinoCore::Model::TicketGrantingTicket.create!({
|
75
73
|
ticket: random_ticket_string('TGC'),
|
74
|
+
authenticator: authentication_result[:authenticator],
|
76
75
|
username: user_data[:username],
|
77
76
|
extra_attributes: user_data[:extra_attributes],
|
78
77
|
user_agent: user_agent
|
@@ -28,8 +28,13 @@ class CASinoCore::Processor::LoginCredentialRequestor < CASinoCore::Processor
|
|
28
28
|
end
|
29
29
|
@listener.user_logged_in(service_url_with_ticket)
|
30
30
|
else
|
31
|
-
|
32
|
-
|
31
|
+
if params[:gateway] == 'true' && params[:service]
|
32
|
+
# we actually lie to the listener to simplify things
|
33
|
+
@listener.user_logged_in(params[:service])
|
34
|
+
else
|
35
|
+
login_ticket = acquire_login_ticket
|
36
|
+
@listener.user_not_logged_in(login_ticket)
|
37
|
+
end
|
33
38
|
end
|
34
39
|
end
|
35
40
|
end
|
@@ -18,7 +18,10 @@ class CASinoCore::Processor::SessionOverview < CASinoCore::Processor
|
|
18
18
|
if tgt.nil?
|
19
19
|
@listener.user_not_logged_in
|
20
20
|
else
|
21
|
-
ticket_granting_tickets = CASinoCore::Model::TicketGrantingTicket.where(
|
21
|
+
ticket_granting_tickets = CASinoCore::Model::TicketGrantingTicket.where(
|
22
|
+
username: tgt.username,
|
23
|
+
authenticator: tgt.authenticator
|
24
|
+
).order('updated_at DESC')
|
22
25
|
@listener.ticket_granting_tickets_found(ticket_granting_tickets)
|
23
26
|
end
|
24
27
|
end
|
data/lib/casino_core/settings.rb
CHANGED
@@ -17,12 +17,12 @@ module CASinoCore
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def authenticators=(authenticators)
|
20
|
-
@authenticators =
|
21
|
-
authenticators.each do |authenticator|
|
20
|
+
@authenticators = {}
|
21
|
+
authenticators.each do |index, authenticator|
|
22
22
|
unless authenticator.is_a?(CASinoCore::Authenticator)
|
23
23
|
authenticator = authenticator[:class].constantize.new(authenticator[:options])
|
24
24
|
end
|
25
|
-
@authenticators
|
25
|
+
@authenticators[index] = authenticator
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -2,9 +2,8 @@ require 'spec_helper'
|
|
2
2
|
require 'nokogiri'
|
3
3
|
|
4
4
|
describe CASinoCore::Model::ServiceTicket::SingleSignOutNotifier do
|
5
|
-
let(:
|
6
|
-
let(:service) {
|
7
|
-
let(:service_ticket) { CASinoCore::Model::ServiceTicket.create ticket: ticket, service: service }
|
5
|
+
let(:service_ticket) { FactoryGirl.create :service_ticket }
|
6
|
+
let(:service) { service_ticket.service }
|
8
7
|
let(:notifier) { described_class.new service_ticket }
|
9
8
|
|
10
9
|
describe '#notify' do
|
@@ -18,7 +17,7 @@ describe CASinoCore::Model::ServiceTicket::SingleSignOutNotifier do
|
|
18
17
|
post_params = CGI.parse(request.body)
|
19
18
|
post_params.should_not be_nil
|
20
19
|
xml = Nokogiri::XML post_params['logoutRequest'].first
|
21
|
-
xml.at_xpath('/samlp:LogoutRequest/samlp:SessionIndex').text.
|
20
|
+
xml.at_xpath('/samlp:LogoutRequest/samlp:SessionIndex').text.should == service_ticket.ticket
|
22
21
|
}
|
23
22
|
end
|
24
23
|
|
@@ -1,16 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CASinoCore::Model::TicketGrantingTicket do
|
4
|
-
let(:
|
5
|
-
let(:service_ticket) {
|
6
|
-
|
7
|
-
}
|
8
|
-
let(:consumed_service_ticket) {
|
9
|
-
service_ticket = subject.service_tickets.create! ticket: 'ST-n9oZvDtYkVFHj5M3s59Ws5', service: 'https://example.com/cas-service'
|
10
|
-
service_ticket.consumed = true
|
11
|
-
service_ticket.save!
|
12
|
-
service_ticket
|
13
|
-
}
|
4
|
+
let(:ticket_granting_ticket) { described_class.create! ticket: 'TGT-3ep9awhy2ty5UhL8wM1xAZ', username: 'example-user', authenticator: 'test' }
|
5
|
+
let(:service_ticket) { FactoryGirl.create :service_ticket, ticket_granting_ticket: ticket_granting_ticket }
|
6
|
+
let(:consumed_service_ticket) { FactoryGirl.create :service_ticket, :consumed, ticket_granting_ticket: ticket_granting_ticket }
|
14
7
|
|
15
8
|
describe '#destroy' do
|
16
9
|
context 'when notification for a service ticket fails' do
|
@@ -21,14 +14,14 @@ describe CASinoCore::Model::TicketGrantingTicket do
|
|
21
14
|
it 'deletes depending proxy-granting tickets' do
|
22
15
|
consumed_service_ticket.proxy_granting_tickets.create! ticket: 'PGT-12345', iou: 'PGTIOU-12345', pgt_url: 'bla'
|
23
16
|
lambda {
|
24
|
-
|
17
|
+
ticket_granting_ticket.destroy
|
25
18
|
}.should change(CASinoCore::Model::ProxyGrantingTicket, :count).by(-1)
|
26
19
|
end
|
27
20
|
|
28
21
|
it 'nullifies depending service tickets' do
|
29
22
|
lambda {
|
30
|
-
|
31
|
-
}.should change { consumed_service_ticket.reload.ticket_granting_ticket_id }.from(
|
23
|
+
ticket_granting_ticket.destroy
|
24
|
+
}.should change { consumed_service_ticket.reload.ticket_granting_ticket_id }.from(ticket_granting_ticket.id).to(nil)
|
32
25
|
end
|
33
26
|
end
|
34
27
|
end
|
@@ -4,18 +4,8 @@ describe CASinoCore::Processor::LegacyValidator do
|
|
4
4
|
describe '#process' do
|
5
5
|
let(:listener) { Object.new }
|
6
6
|
let(:processor) { described_class.new(listener) }
|
7
|
-
let(:
|
8
|
-
let(:
|
9
|
-
CASinoCore::Model::TicketGrantingTicket.create!({
|
10
|
-
ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
|
11
|
-
username: 'test',
|
12
|
-
extra_attributes: nil,
|
13
|
-
user_agent: user_agent
|
14
|
-
})
|
15
|
-
}
|
16
|
-
let(:service) { 'https://example.com/cas-service' }
|
17
|
-
let(:service_ticket) { ticket_granting_ticket.service_tickets.create! ticket: 'ST-2nOcXx56dtPTsB069yYf0h', service: service }
|
18
|
-
let(:parameters) { { service: service, ticket: service_ticket.ticket }}
|
7
|
+
let(:service_ticket) { FactoryGirl.create :service_ticket }
|
8
|
+
let(:parameters) { { service: service_ticket.service, ticket: service_ticket.ticket }}
|
19
9
|
|
20
10
|
before(:each) do
|
21
11
|
listener.stub(:validation_failed)
|
@@ -12,8 +12,17 @@ describe CASinoCore::Processor::LoginCredentialAcceptor do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
context 'with an expired login ticket' do
|
16
|
+
let(:expired_login_ticket) { FactoryGirl.create :login_ticket, :expired }
|
17
|
+
|
18
|
+
it 'calls the #invalid_login_ticket method on the listener' do
|
19
|
+
listener.should_receive(:invalid_login_ticket).with(kind_of(CASinoCore::Model::LoginTicket))
|
20
|
+
processor.process(lt: expired_login_ticket.ticket)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
15
24
|
context 'with a valid login ticket' do
|
16
|
-
let(:login_ticket) {
|
25
|
+
let(:login_ticket) { FactoryGirl.create :login_ticket }
|
17
26
|
|
18
27
|
context 'with invalid credentials' do
|
19
28
|
it 'calls the #invalid_login_credentials method on the listener' do
|
@@ -10,18 +10,32 @@ describe CASinoCore::Processor::LoginCredentialRequestor do
|
|
10
10
|
listener.should_receive(:user_not_logged_in).with(kind_of(CASinoCore::Model::LoginTicket))
|
11
11
|
processor.process
|
12
12
|
end
|
13
|
+
|
14
|
+
context 'with gateway parameter' do
|
15
|
+
context 'with a service' do
|
16
|
+
let(:service) { 'http://example.com/' }
|
17
|
+
let(:params) { { service: service, gateway: 'true' } }
|
18
|
+
|
19
|
+
it 'calls the #user_logged_in method on the listener' do
|
20
|
+
listener.should_receive(:user_logged_in).with(service)
|
21
|
+
processor.process(params)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'without a service' do
|
26
|
+
let(:params) { { gateway: 'true' } }
|
27
|
+
|
28
|
+
it 'calls the #user_not_logged_in method on the listener' do
|
29
|
+
listener.should_receive(:user_not_logged_in).with(kind_of(CASinoCore::Model::LoginTicket))
|
30
|
+
processor.process
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
13
34
|
end
|
14
35
|
|
15
36
|
context 'when logged in' do
|
16
|
-
let(:
|
17
|
-
let(:
|
18
|
-
CASinoCore::Model::TicketGrantingTicket.create!({
|
19
|
-
ticket: 'TGC-9H6Vx4850i2Ksp3R8hTCwO',
|
20
|
-
username: 'test',
|
21
|
-
extra_attributes: nil,
|
22
|
-
user_agent: user_agent
|
23
|
-
})
|
24
|
-
}
|
37
|
+
let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
|
38
|
+
let(:user_agent) { ticket_granting_ticket.user_agent }
|
25
39
|
let(:cookies) { { tgt: ticket_granting_ticket.ticket } }
|
26
40
|
|
27
41
|
before(:each) do
|
@@ -64,9 +78,11 @@ describe CASinoCore::Processor::LoginCredentialRequestor do
|
|
64
78
|
end
|
65
79
|
|
66
80
|
context 'with a changed browser' do
|
81
|
+
let(:user_agent) { 'FooBar 1.0' }
|
82
|
+
|
67
83
|
it 'calls the #user_not_logged_in method on the listener' do
|
68
84
|
listener.should_receive(:user_not_logged_in).with(kind_of(CASinoCore::Model::LoginTicket))
|
69
|
-
processor.process(nil, cookies)
|
85
|
+
processor.process(nil, cookies, user_agent)
|
70
86
|
end
|
71
87
|
end
|
72
88
|
end
|
@@ -7,22 +7,15 @@ describe CASinoCore::Processor::Logout do
|
|
7
7
|
let(:cookies) { { tgt: tgt } }
|
8
8
|
let(:url) { nil }
|
9
9
|
let(:params) { { :url => url } unless url.nil? }
|
10
|
-
let(:user_agent) { 'TestBrowser 1.0' }
|
11
10
|
|
12
11
|
before(:each) do
|
13
12
|
listener.stub(:user_logged_out)
|
14
13
|
end
|
15
14
|
|
16
15
|
context 'with an existing ticket-granting ticket' do
|
17
|
-
let(:ticket_granting_ticket) {
|
18
|
-
CASinoCore::Model::TicketGrantingTicket.create!({
|
19
|
-
ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
|
20
|
-
username: 'test',
|
21
|
-
extra_attributes: nil,
|
22
|
-
user_agent: user_agent
|
23
|
-
})
|
24
|
-
}
|
16
|
+
let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
|
25
17
|
let(:tgt) { ticket_granting_ticket.ticket }
|
18
|
+
let(:user_agent) { ticket_granting_ticket.user_agent }
|
26
19
|
|
27
20
|
it 'deletes the ticket-granting ticket' do
|
28
21
|
processor.process(params, cookies, user_agent)
|
@@ -40,16 +40,7 @@ describe CASinoCore::Processor::ProxyTicketProvider do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
context 'with a proxy-granting ticket' do
|
43
|
-
let(:
|
44
|
-
CASinoCore::Model::TicketGrantingTicket.create!({
|
45
|
-
ticket: 'TGC-Qu6B5IVQ7RmLc972TruM9u',
|
46
|
-
username: 'test'
|
47
|
-
})
|
48
|
-
}
|
49
|
-
let(:service_ticket) { ticket_granting_ticket.service_tickets.create! ticket: 'ST-2nOcXx56dtPTsB069yYf0h', service: 'http://www.example.com/' }
|
50
|
-
let(:proxy_granting_ticket) {
|
51
|
-
service_ticket.proxy_granting_tickets.create! ticket: 'PGT-OIE42ZadV3B9VcaG2xMjAf', iou: 'PGTIOU-PYg4CCPQHNyyS9s6bJF6Rg', pgt_url: 'https://www.example.com/pgtUrl'
|
52
|
-
}
|
43
|
+
let(:proxy_granting_ticket) { FactoryGirl.create :proxy_granting_ticket }
|
53
44
|
let(:params_with_valid_pgt) { params.merge(pgt: proxy_granting_ticket.ticket) }
|
54
45
|
|
55
46
|
it 'calls the #request_succeeded method on the listener' do
|
@@ -7,21 +7,20 @@ describe CASinoCore::Processor::ProxyTicketValidator do
|
|
7
7
|
describe '#process' do
|
8
8
|
let(:regex_success) { /\A<cas:serviceResponse.*\n.*authenticationSuccess/ }
|
9
9
|
|
10
|
+
context 'with a login ticket' do
|
11
|
+
let(:login_ticket) { FactoryGirl.create :login_ticket }
|
12
|
+
let(:parameters) { { ticket: login_ticket.ticket, service: 'http://www.example.org/' } }
|
13
|
+
|
14
|
+
it 'calls the #validation_failed method on the listener' do
|
15
|
+
listener.should_receive(:validation_failed)
|
16
|
+
processor.process(parameters)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
10
20
|
context 'with an unconsumed proxy ticket' do
|
11
|
-
let(:
|
12
|
-
|
13
|
-
|
14
|
-
username: 'test'
|
15
|
-
})
|
16
|
-
}
|
17
|
-
let(:service_ticket) { ticket_granting_ticket.service_tickets.create! ticket: 'ST-2nOcXx56dtPTsB069yYf0h', service: 'http://www.example.com/' }
|
18
|
-
let(:proxy_granting_ticket) {
|
19
|
-
service_ticket.proxy_granting_tickets.create! ticket: 'PGT-OIE42ZadV3B9VcaG2xMjAf', iou: 'PGTIOU-PYg4CCPQHNyyS9s6bJF6Rg', pgt_url: 'https://www.example.com/pgtUrl'
|
20
|
-
}
|
21
|
-
let(:proxy_service) { 'imaps://127.0.0.1:4578/' }
|
22
|
-
let(:proxy_ticket) { proxy_granting_ticket.proxy_tickets.create! ticket: 'PT-8nA7vuxuNY7RcpVoaDvuZi', service: proxy_service }
|
23
|
-
let(:parameters) { { ticket: proxy_ticket.ticket, service: proxy_service } }
|
24
|
-
let(:regex_proxy) { /<cas:proxies>\s*<cas:proxy>https:\/\/www.example.com\/pgtUrl<\/cas:proxy>\s*<\/cas:proxies[>]/ }
|
21
|
+
let(:proxy_ticket) { FactoryGirl.create :proxy_ticket }
|
22
|
+
let(:parameters) { { ticket: proxy_ticket.ticket, service: proxy_ticket.service } }
|
23
|
+
let(:regex_proxy) { /<cas:proxies>\s*<cas:proxy>#{proxy_ticket.proxy_granting_ticket.pgt_url}<\/cas:proxy>\s*<\/cas:proxies>/ }
|
25
24
|
|
26
25
|
it 'calls the #validation_succeeded method on the listener' do
|
27
26
|
listener.should_receive(:validation_succeeded).with(regex_success)
|
@@ -4,15 +4,8 @@ describe CASinoCore::Processor::SessionDestroyer do
|
|
4
4
|
describe '#process' do
|
5
5
|
let(:listener) { Object.new }
|
6
6
|
let(:processor) { described_class.new(listener) }
|
7
|
-
let(:
|
8
|
-
let(:
|
9
|
-
CASinoCore::Model::TicketGrantingTicket.create!({
|
10
|
-
ticket: 'TGC-ocCudGzZjJtrvOXJ485mt3',
|
11
|
-
username: 'test',
|
12
|
-
extra_attributes: nil,
|
13
|
-
user_agent: user_agent
|
14
|
-
})
|
15
|
-
}
|
7
|
+
let(:owner_ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
|
8
|
+
let(:user_agent) { owner_ticket_granting_ticket.user_agent }
|
16
9
|
let(:cookies) { { tgt: owner_ticket_granting_ticket.ticket } }
|
17
10
|
|
18
11
|
before(:each) do
|
@@ -21,23 +14,9 @@ describe CASinoCore::Processor::SessionDestroyer do
|
|
21
14
|
end
|
22
15
|
|
23
16
|
context 'with an existing ticket-granting ticket' do
|
24
|
-
let(:ticket_granting_ticket) {
|
25
|
-
|
26
|
-
|
27
|
-
username: 'test',
|
28
|
-
extra_attributes: nil,
|
29
|
-
user_agent: user_agent
|
30
|
-
})
|
31
|
-
}
|
32
|
-
let(:service_ticket) {
|
33
|
-
ticket_granting_ticket.service_tickets.create! ticket: 'ST-6NBRr5DAg2NW181H5chaHh', service: 'http://www.example.com'
|
34
|
-
}
|
35
|
-
let(:consumed_service_ticket) {
|
36
|
-
st = ticket_granting_ticket.service_tickets.create! ticket: 'ST-6NBRr5DAg2NW181H5chaHh', service: 'http://www.example.com'
|
37
|
-
st.consumed = true
|
38
|
-
st.save!
|
39
|
-
st
|
40
|
-
}
|
17
|
+
let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
|
18
|
+
let(:service_ticket) { FactoryGirl.create :service_ticket, ticket_granting_ticket: ticket_granting_ticket }
|
19
|
+
let(:consumed_service_ticket) { FactoryGirl.create :service_ticket, :consumed, ticket_granting_ticket: ticket_granting_ticket }
|
41
20
|
let(:params) { { id: ticket_granting_ticket.id } }
|
42
21
|
|
43
22
|
it 'deletes only one ticket-granting ticket' do
|
@@ -75,14 +54,7 @@ describe CASinoCore::Processor::SessionDestroyer do
|
|
75
54
|
end
|
76
55
|
|
77
56
|
context 'when trying to delete ticket-granting ticket of another user' do
|
78
|
-
let(:ticket_granting_ticket) {
|
79
|
-
CASinoCore::Model::TicketGrantingTicket.create!({
|
80
|
-
ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
|
81
|
-
username: 'this_is_another_user',
|
82
|
-
extra_attributes: nil,
|
83
|
-
user_agent: user_agent
|
84
|
-
})
|
85
|
-
}
|
57
|
+
let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket, username: 'other_user' }
|
86
58
|
let(:params) { { id: ticket_granting_ticket.id } }
|
87
59
|
|
88
60
|
it 'does not delete a ticket-granting ticket' do
|
@@ -4,15 +4,8 @@ describe CASinoCore::Processor::SessionOverview do
|
|
4
4
|
describe '#process' do
|
5
5
|
let(:listener) { Object.new }
|
6
6
|
let(:processor) { described_class.new(listener) }
|
7
|
-
let(:
|
8
|
-
let(:
|
9
|
-
CASinoCore::Model::TicketGrantingTicket.create!({
|
10
|
-
ticket: 'TGC-ocCudGzZjJtrvOXJ485mt3',
|
11
|
-
username: 'test',
|
12
|
-
extra_attributes: nil,
|
13
|
-
user_agent: user_agent
|
14
|
-
})
|
15
|
-
}
|
7
|
+
let(:other_ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
|
8
|
+
let(:user_agent) { other_ticket_granting_ticket.user_agent }
|
16
9
|
let(:cookies) { { tgt: tgt } }
|
17
10
|
|
18
11
|
before(:each) do
|
@@ -22,14 +15,7 @@ describe CASinoCore::Processor::SessionOverview do
|
|
22
15
|
end
|
23
16
|
|
24
17
|
context 'with an existing ticket-granting ticket' do
|
25
|
-
let(:ticket_granting_ticket) {
|
26
|
-
CASinoCore::Model::TicketGrantingTicket.create!({
|
27
|
-
ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
|
28
|
-
username: 'test',
|
29
|
-
extra_attributes: nil,
|
30
|
-
user_agent: user_agent
|
31
|
-
})
|
32
|
-
}
|
18
|
+
let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
|
33
19
|
let(:tgt) { ticket_granting_ticket.ticket }
|
34
20
|
it 'calls the #ticket_granting_tickets_found method on the listener' do
|
35
21
|
listener.should_receive(:ticket_granting_tickets_found) do |tickets|
|
@@ -39,6 +25,18 @@ describe CASinoCore::Processor::SessionOverview do
|
|
39
25
|
end
|
40
26
|
end
|
41
27
|
|
28
|
+
context 'with a ticket-granting ticket with same username but different authenticator' do
|
29
|
+
let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket, authenticator: 'other' }
|
30
|
+
let(:tgt) { ticket_granting_ticket.ticket }
|
31
|
+
|
32
|
+
it 'calls the #ticket_granting_tickets_found method on the listener' do
|
33
|
+
listener.should_receive(:ticket_granting_tickets_found) do |tickets|
|
34
|
+
tickets.length.should == 1
|
35
|
+
end
|
36
|
+
processor.process(cookies, user_agent)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
42
40
|
context 'with an invalid ticket-granting ticket' do
|
43
41
|
let(:tgt) { 'TGT-lalala' }
|
44
42
|
it 'calls the #user_not_logged_in method on the listener' do
|
@@ -5,19 +5,8 @@ require 'spec_helper'
|
|
5
5
|
describe '#process' do
|
6
6
|
let(:listener) { Object.new }
|
7
7
|
let(:processor) { described_class.new(listener) }
|
8
|
-
let(:
|
9
|
-
let(:
|
10
|
-
CASinoCore::Model::TicketGrantingTicket.create!({
|
11
|
-
ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
|
12
|
-
username: 'test',
|
13
|
-
extra_attributes: { name: "Example User", roles: ['User', 'Admin'] },
|
14
|
-
user_agent: user_agent
|
15
|
-
})
|
16
|
-
}
|
17
|
-
let(:service) { 'https://www.example.com/cas-service' }
|
18
|
-
let(:service_ticket) { ticket_granting_ticket.service_tickets.create! ticket: 'ST-2nOcXx56dtPTsB069yYf0h', service: service }
|
19
|
-
let(:parameters) { { service: service, ticket: service_ticket.ticket }}
|
20
|
-
|
8
|
+
let(:service_ticket) { FactoryGirl.create :service_ticket }
|
9
|
+
let(:parameters) { { service: service_ticket.service, ticket: service_ticket.ticket }}
|
21
10
|
let(:regex_failure) { /\A\<cas\:serviceResponse.*\n.*authenticationFailure/ }
|
22
11
|
let(:regex_success) { /\A\<cas\:serviceResponse.*\n.*authenticationSuccess/ }
|
23
12
|
|
@@ -26,6 +15,19 @@ require 'spec_helper'
|
|
26
15
|
listener.stub(:validation_succeeded)
|
27
16
|
end
|
28
17
|
|
18
|
+
context 'without all required parameters' do
|
19
|
+
[:ticket, :service].each do |missing_parameter|
|
20
|
+
let(:invalid_parameters) { parameters.except(missing_parameter) }
|
21
|
+
|
22
|
+
context "without '#{missing_parameter}'" do
|
23
|
+
it 'calls the #validation_failed method on the listener' do
|
24
|
+
listener.should_receive(:validation_failed).with(regex_failure)
|
25
|
+
processor.process(invalid_parameters)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
29
31
|
context 'with an unconsumed service ticket' do
|
30
32
|
context 'without renew flag' do
|
31
33
|
it 'consumes the service ticket' do
|
@@ -43,7 +45,7 @@ require 'spec_helper'
|
|
43
45
|
context 'with empty query values' do
|
44
46
|
it 'calls the #validation_succeeded method on the listener' do
|
45
47
|
listener.should_receive(:validation_succeeded).with(regex_success)
|
46
|
-
processor.process(parameters.merge(service: "#{service}/?"))
|
48
|
+
processor.process(parameters.merge(service: "#{service_ticket.service}/?"))
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
data/spec/spec_helper.rb
CHANGED
@@ -10,6 +10,11 @@ require 'simplecov'
|
|
10
10
|
# loaded once.
|
11
11
|
#
|
12
12
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
13
|
+
|
14
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
15
|
+
# in spec/support/ and its subdirectories.
|
16
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
17
|
+
|
13
18
|
RSpec.configure do |config|
|
14
19
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
15
20
|
|
@@ -21,6 +26,12 @@ RSpec.configure do |config|
|
|
21
26
|
|
22
27
|
SimpleCov.start do
|
23
28
|
add_filter '/spec'
|
29
|
+
base_path = "#{File.dirname(__FILE__)}/../"
|
30
|
+
Dir["#{base_path}lib/casino_core/*.rb"].each do |f|
|
31
|
+
f.gsub!(/\A#{base_path}(.+)\.rb\z/, '\1')
|
32
|
+
name = File.basename(f).humanize.pluralize
|
33
|
+
add_group name, f
|
34
|
+
end
|
24
35
|
end
|
25
36
|
|
26
37
|
CASinoCore.setup 'test'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'factory_girl'
|
2
|
+
|
3
|
+
FactoryGirl.define do
|
4
|
+
factory :login_ticket, class: CASinoCore::Model::LoginTicket do
|
5
|
+
sequence :ticket do |n|
|
6
|
+
"LT-ticket#{n}"
|
7
|
+
end
|
8
|
+
|
9
|
+
trait :consumed do
|
10
|
+
consumed true
|
11
|
+
end
|
12
|
+
trait :expired do
|
13
|
+
created_at 601.seconds.ago
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'factory_girl'
|
2
|
+
|
3
|
+
FactoryGirl.define do
|
4
|
+
factory :proxy_granting_ticket, class: CASinoCore::Model::ProxyGrantingTicket do
|
5
|
+
association :granter, factory: :service_ticket
|
6
|
+
sequence :ticket do |n|
|
7
|
+
"PGT-ticket#{n}"
|
8
|
+
end
|
9
|
+
sequence :iou do |n|
|
10
|
+
"PGTIOU-ticket#{n}"
|
11
|
+
end
|
12
|
+
sequence :pgt_url do |n|
|
13
|
+
"https://www#{n}.example.org/pgtUrl"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'factory_girl'
|
2
|
+
|
3
|
+
FactoryGirl.define do
|
4
|
+
factory :proxy_ticket, class: CASinoCore::Model::ProxyTicket do
|
5
|
+
proxy_granting_ticket
|
6
|
+
sequence :ticket do |n|
|
7
|
+
"PT-ticket#{n}"
|
8
|
+
end
|
9
|
+
sequence :service do |n|
|
10
|
+
"imaps://mail#{n}.example.org/"
|
11
|
+
end
|
12
|
+
|
13
|
+
trait :consumed do
|
14
|
+
consumed true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'factory_girl'
|
2
|
+
|
3
|
+
FactoryGirl.define do
|
4
|
+
factory :service_ticket, class: CASinoCore::Model::ServiceTicket do
|
5
|
+
ticket_granting_ticket
|
6
|
+
sequence :ticket do |n|
|
7
|
+
"ST-ticket#{n}"
|
8
|
+
end
|
9
|
+
sequence :service do |n|
|
10
|
+
"http://www#{n}.example.org/"
|
11
|
+
end
|
12
|
+
|
13
|
+
trait :consumed do
|
14
|
+
consumed true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'factory_girl'
|
2
|
+
|
3
|
+
FactoryGirl.define do
|
4
|
+
factory :ticket_granting_ticket, class: CASinoCore::Model::TicketGrantingTicket do
|
5
|
+
sequence :ticket do |n|
|
6
|
+
"TGC-ticket#{n}"
|
7
|
+
end
|
8
|
+
authenticator 'test'
|
9
|
+
username 'test'
|
10
|
+
extra_attributes({ fullname: "Test User", age: 15, roles: [:user] })
|
11
|
+
user_agent 'TestBrowser 1.0'
|
12
|
+
end
|
13
|
+
end
|
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.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Nils Caspar
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-12-
|
13
|
+
date: 2012-12-30 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -155,6 +155,17 @@ dependencies:
|
|
155
155
|
type: :development
|
156
156
|
prerelease: false
|
157
157
|
version_requirements: *id013
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: factory_girl
|
160
|
+
requirement: &id014 !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ~>
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: 4.1.0
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: *id014
|
158
169
|
description: A CAS server core library.
|
159
170
|
email: ncaspar@me.com
|
160
171
|
executables: []
|
@@ -196,6 +207,7 @@ files:
|
|
196
207
|
- db/migrate/20121225231713_no_default_granter_type.rb
|
197
208
|
- db/migrate/20121226192211_fix_index_for_granter_on_proxy_granting_ticket.rb
|
198
209
|
- db/migrate/20121226211511_allow_service_tickets_without_ticket_granting_ticket.rb
|
210
|
+
- db/migrate/20121231114141_add_authenticator_to_ticket_granting_tickets.rb
|
199
211
|
- db/schema.rb
|
200
212
|
- lib/casino_core.rb
|
201
213
|
- lib/casino_core/authenticator.rb
|
@@ -250,6 +262,11 @@ files:
|
|
250
262
|
- spec/processor/session_overview_spec.rb
|
251
263
|
- spec/processor/ticket_validator_spec.rb
|
252
264
|
- spec/spec_helper.rb
|
265
|
+
- spec/support/factories/login_ticket_factory.rb
|
266
|
+
- spec/support/factories/proxy_granting_ticket_factory.rb
|
267
|
+
- spec/support/factories/proxy_ticket_factory.rb
|
268
|
+
- spec/support/factories/service_ticket_factory.rb
|
269
|
+
- spec/support/factories/ticket_granting_ticket_factory.rb
|
253
270
|
homepage: http://github.com/pencil/CASinoCore
|
254
271
|
licenses:
|
255
272
|
- MIT
|
@@ -263,7 +280,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
263
280
|
requirements:
|
264
281
|
- - ">="
|
265
282
|
- !ruby/object:Gem::Version
|
266
|
-
hash:
|
283
|
+
hash: -1912000289096139821
|
267
284
|
segments:
|
268
285
|
- 0
|
269
286
|
version: "0"
|