casablanca 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -1
- data/Manifest.txt +1 -1
- data/{README.textile → README.txt} +27 -13
- data/Rakefile +6 -5
- data/bin/casablanca +3 -2
- data/lib/casablanca.rb +1 -1
- data/lib/casablanca/cli.rb +9 -5
- data/lib/casablanca/client.rb +119 -35
- data/lib/casablanca/filters/rails.rb +59 -29
- data/test/test_client.rb +48 -13
- data/test/test_helper.rb +5 -5
- data/test/test_rails_filter.rb +44 -37
- data/test/test_ticket.rb +10 -14
- metadata +7 -6
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -1,18 +1,29 @@
|
|
1
|
-
|
1
|
+
= Casablanca
|
2
2
|
|
3
|
-
|
3
|
+
* http://rubyforge.org/projects/casablanca/
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
4
6
|
|
5
7
|
Casablanca is a single sign-on client for the CAS 2.0 protocol.
|
6
|
-
It can be run from the commandline and as a filter for Rails.
|
7
8
|
|
8
|
-
|
9
|
+
== FEATURES:
|
10
|
+
|
11
|
+
* Includes a commandline Client to test getting service tickets from a CAS server
|
12
|
+
* It can be run as a Rails plugin.
|
13
|
+
* Gatewaying (permitting the user to continue without authentication).
|
14
|
+
|
15
|
+
== TODO:
|
9
16
|
|
17
|
+
* Add extra attributes returned from the server
|
18
|
+
* Implement proxing
|
19
|
+
* Check for single signout
|
20
|
+
* Check for endless redirects
|
10
21
|
|
11
|
-
|
22
|
+
== SYNOPSIS:
|
12
23
|
|
13
24
|
Commandline:
|
14
25
|
|
15
|
-
casablanca
|
26
|
+
% casablanca
|
16
27
|
|
17
28
|
In IRB:
|
18
29
|
|
@@ -31,6 +42,8 @@ In a Rails project:
|
|
31
42
|
Casablanca::RailsFilter.config do |config|
|
32
43
|
config[:cas_server_url] = "http://localhost:4567"
|
33
44
|
config[:service_url] = "http://localhost:3000"
|
45
|
+
# Always require new credentials for authentication
|
46
|
+
config[:renew] = true
|
34
47
|
end
|
35
48
|
|
36
49
|
- Add the following to application.rb:
|
@@ -52,16 +65,17 @@ In a Rails project:
|
|
52
65
|
- Add the following to you logout action
|
53
66
|
|
54
67
|
Casablanca::RailsFilter.logout(self)
|
68
|
+
|
69
|
+
== REQUIREMENTS:
|
55
70
|
|
56
|
-
|
71
|
+
== INSTALL:
|
57
72
|
|
58
|
-
|
59
|
-
*
|
60
|
-
|
61
|
-
*
|
62
|
-
* Check for endless redirects
|
73
|
+
Stable version
|
74
|
+
* sudo gem install casablanca
|
75
|
+
Development version
|
76
|
+
* gem sources -a http://gems.github.com; sudo gem install p8-casablanca
|
63
77
|
|
64
|
-
|
78
|
+
== LICENSE:
|
65
79
|
|
66
80
|
(The MIT License)
|
67
81
|
|
data/Rakefile
CHANGED
@@ -6,10 +6,11 @@ require 'lib/casablanca.rb'
|
|
6
6
|
|
7
7
|
Hoe.new('casablanca', Casablanca::VERSION) do |p|
|
8
8
|
p.developer('FIX', 'FIX@example.com')
|
9
|
+
p.remote_rdoc_dir = '' # Release to root
|
9
10
|
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
require 'metric_fu'
|
13
|
+
|
14
|
+
MetricFu::Configuration.run do |config|
|
15
|
+
config.coverage = { :test_files => ['test/**/test_*.rb'] }
|
16
|
+
end
|
data/bin/casablanca
CHANGED
@@ -3,7 +3,8 @@ irb = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
|
|
3
3
|
options = { :sandbox => false, :irb => irb }
|
4
4
|
|
5
5
|
libs = " -r irb/completion"
|
6
|
-
libs << " -r #{File.dirname(__FILE__)}/../lib/casablanca.rb"
|
7
|
-
libs << " -r #{File.dirname(__FILE__)}/../lib/casablanca/
|
6
|
+
libs << " -r #{File.expand_path(File.dirname(__FILE__))}/../lib/casablanca.rb"
|
7
|
+
libs << " -r #{File.expand_path(File.dirname(__FILE__))}/../lib/casablanca/client.rb"
|
8
|
+
libs << " -r #{File.expand_path(File.dirname(__FILE__))}/../lib/casablanca/cli.rb"
|
8
9
|
|
9
10
|
exec "#{options[:irb]} #{libs} --simple-prompt"
|
data/lib/casablanca.rb
CHANGED
data/lib/casablanca/cli.rb
CHANGED
@@ -6,15 +6,19 @@ CASABLANCA CLIENT CONSOLE (#{Casablanca::VERSION})
|
|
6
6
|
Use C for a configured client (#{config.inspect})
|
7
7
|
Example:
|
8
8
|
|
9
|
-
t = C.
|
10
|
-
C.authenticate_ticket(t)
|
9
|
+
t = C.login('admin', 'admin')
|
10
|
+
C.authenticate_ticket(t)
|
11
|
+
|
12
|
+
C.logout
|
11
13
|
|
12
14
|
The configuration can be changed:
|
13
|
-
|
14
|
-
C.
|
15
|
+
|
16
|
+
C.cas_server_url = "http://example.com/cas_server"
|
17
|
+
C.service_url = "http://example.com/application"
|
15
18
|
|
16
19
|
)
|
17
20
|
|
18
|
-
C =
|
21
|
+
C = Casablanca::CommandLineClient.new(config)
|
22
|
+
C.logger.level = Logger::DEBUG
|
19
23
|
|
20
24
|
puts INFO
|
data/lib/casablanca/client.rb
CHANGED
@@ -2,9 +2,10 @@ require 'uri'
|
|
2
2
|
require 'cgi'
|
3
3
|
require 'net/https'
|
4
4
|
require 'rexml/document'
|
5
|
+
require 'logger'
|
5
6
|
|
6
7
|
module Casablanca
|
7
|
-
|
8
|
+
|
8
9
|
class Client
|
9
10
|
attr_accessor :cas_server_url, :service_url
|
10
11
|
|
@@ -14,23 +15,60 @@ module Casablanca
|
|
14
15
|
@service_url = config[:service_url]
|
15
16
|
end
|
16
17
|
|
18
|
+
##
|
19
|
+
# Validates a Ticket to the validation url of the CAS Server
|
20
|
+
# and checks if the ticket is authenticated
|
17
21
|
def authenticate_ticket(ticket)
|
18
|
-
|
19
|
-
ticket.authenticate
|
22
|
+
request_validation(ticket)
|
23
|
+
ticket.authenticate
|
20
24
|
end
|
21
25
|
|
22
|
-
|
23
|
-
|
26
|
+
##
|
27
|
+
# The login url of the Cas server. This page has the login form.
|
28
|
+
def login_url(params={})
|
29
|
+
uri = URI.parse("#{@cas_server_url}/login")
|
30
|
+
query = {:service => @service_url}
|
31
|
+
query[:renew] = 'true' if params[:renew]
|
32
|
+
uri.merge_query(query)
|
33
|
+
uri.to_s
|
24
34
|
end
|
25
35
|
|
26
|
-
|
27
|
-
|
36
|
+
##
|
37
|
+
# The logout url of the Cas server
|
38
|
+
def logout_url(params={})
|
39
|
+
uri = URI.parse("#{@cas_server_url}/logout")
|
40
|
+
query = {}
|
41
|
+
query[:url] = params[:url] if params[:url]
|
42
|
+
uri.merge_query(query)
|
43
|
+
uri.to_s
|
28
44
|
end
|
29
45
|
|
46
|
+
##
|
47
|
+
# The proxy validation url of the Cas server.
|
30
48
|
def validate_url
|
31
49
|
"#{@cas_server_url}/proxyValidate"
|
32
50
|
end
|
33
51
|
|
52
|
+
def logger
|
53
|
+
self.class.logger
|
54
|
+
end
|
55
|
+
|
56
|
+
def logger=logger
|
57
|
+
self.class.logger = logger
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.logger=logger
|
61
|
+
@logger = logger
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.logger
|
65
|
+
unless @logger
|
66
|
+
@logger = ::Logger.new($stderr)
|
67
|
+
@logger.level = Logger::WARN
|
68
|
+
end
|
69
|
+
@logger
|
70
|
+
end
|
71
|
+
|
34
72
|
private
|
35
73
|
|
36
74
|
def request_validation(ticket)
|
@@ -38,95 +76,134 @@ module Casablanca
|
|
38
76
|
uri = URI.parse(validate_url)
|
39
77
|
uri.merge_query(ticket.to_request_params)
|
40
78
|
response = get(uri)
|
41
|
-
puts "#{@cas_server_url} #{response.inspect}:\n#{response.body}"
|
42
79
|
unless response.kind_of?(Net::HTTPSuccess)
|
43
80
|
raise ResponseError, "#{response.code}, #{response.body}"
|
44
81
|
end
|
45
|
-
response.body
|
82
|
+
ticket.body = response.body
|
46
83
|
end
|
47
84
|
|
48
85
|
def get(uri)
|
49
86
|
https(uri) do |h|
|
50
|
-
h.get("#{uri.path}?#{uri.query}")
|
51
|
-
end
|
87
|
+
h.get("#{uri.path}?#{uri.query}", headers)
|
88
|
+
end
|
52
89
|
end
|
53
90
|
|
54
91
|
def https(uri)
|
55
92
|
https = Net::HTTP.new(uri.host, uri.port)
|
56
93
|
https.use_ssl = (uri.scheme == 'https')
|
57
94
|
begin
|
58
|
-
https.start do |h|
|
95
|
+
response = https.start do |h|
|
59
96
|
yield(h)
|
60
97
|
end
|
61
98
|
rescue Errno::ECONNREFUSED => error
|
62
99
|
raise CasServerException
|
63
100
|
end
|
101
|
+
logger.debug(response_log(response))
|
102
|
+
response
|
103
|
+
end
|
104
|
+
|
105
|
+
def headers
|
106
|
+
{'cookie' => @ticket_granting_ticket || ''}
|
107
|
+
end
|
108
|
+
|
109
|
+
def response_log(response)
|
110
|
+
msg = "################\n"
|
111
|
+
msg << " #{@cas_server_url} #{response.inspect}:\n"
|
112
|
+
msg << " body: #{response.body}\n"
|
113
|
+
msg << " headers:\n"
|
114
|
+
response.each_key do |k|
|
115
|
+
msg << " - #{k}: #{response[k]}\n"
|
116
|
+
end
|
117
|
+
msg
|
64
118
|
end
|
65
119
|
|
66
120
|
end
|
67
121
|
|
68
122
|
class CommandLineClient < Client
|
69
|
-
|
123
|
+
attr_reader :ticket_granting_ticket
|
124
|
+
##
|
125
|
+
# Logs in to the CAS server and returns the response
|
70
126
|
def login(username, password)
|
71
|
-
|
127
|
+
@ticket_granting_ticket = nil
|
128
|
+
response = post(URI.parse(login_url), {:username => username, :password => password, :service => service_url})
|
129
|
+
set_ticket_granting_ticket(response)
|
130
|
+
get_service_ticket(response)
|
72
131
|
end
|
73
132
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
133
|
+
def logout(follow_url=nil)
|
134
|
+
@ticket_granting_ticket = nil
|
135
|
+
uri = URI.parse(logout_url)
|
136
|
+
uri.merge_query(:url => follow_url) if follow_url
|
137
|
+
get(uri)
|
79
138
|
end
|
80
|
-
|
139
|
+
|
81
140
|
private
|
82
|
-
|
141
|
+
|
83
142
|
def post(uri, form_data)
|
84
143
|
req = Net::HTTP::Post.new(uri.path)
|
85
144
|
req.set_form_data(form_data, ';')
|
86
145
|
https(uri) do |h|
|
87
146
|
h.request(req)
|
88
147
|
end
|
89
|
-
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_service_ticket(response)
|
151
|
+
if (location = response['location'])
|
152
|
+
query = {}
|
153
|
+
URI.parse(location).query.collect{|q| k,v = q.split('='); query[k] = v }
|
154
|
+
Ticket.new(query['ticket'], @service_url)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def set_ticket_granting_ticket(response)
|
159
|
+
@ticket_granting_ticket = (response['set-cookie'] || '').split(/;/)[0] # tgt=TGC-1232569033r763536CC6753E6F357
|
160
|
+
end
|
90
161
|
end
|
91
162
|
|
92
163
|
class Ticket
|
93
164
|
attr_accessor :user, :failure_code, :failure_message
|
94
165
|
attr_reader :service_url, :ticket
|
95
|
-
|
166
|
+
attr_writer :body
|
96
167
|
def initialize(ticket, service_url, renew = false)
|
97
168
|
@service_url = service_url
|
98
169
|
@ticket = ticket
|
99
|
-
@renew
|
170
|
+
@renew = renew
|
100
171
|
end
|
101
172
|
|
173
|
+
##
|
174
|
+
# Create a Ticket from a Hash. Useful for unserializing
|
102
175
|
def self.from_hash(hash)
|
103
|
-
ticket = Ticket.new(hash[:ticket], hash[:service_url]
|
176
|
+
ticket = Ticket.new(hash[:ticket], hash[:service_url])
|
104
177
|
ticket.user = hash[:user]
|
105
178
|
ticket
|
106
179
|
end
|
107
180
|
|
108
|
-
|
109
|
-
|
110
|
-
:ticket => @ticket }
|
111
|
-
params[:renew] = 1 if @renew
|
112
|
-
params
|
113
|
-
end
|
114
|
-
|
181
|
+
##
|
182
|
+
# Convert a Ticket to a Hash. Useful for serializing
|
115
183
|
def to_hash
|
116
184
|
props = {}
|
117
185
|
props[:user] = @user if authenticated?
|
118
|
-
props[:renew] = @renew if @renew
|
119
186
|
props[:service_url] = @service_url
|
120
187
|
props[:ticket] = @ticket
|
121
188
|
props
|
122
189
|
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# Convert the ticket to a Hash for a request
|
193
|
+
def to_request_params
|
194
|
+
params = {}
|
195
|
+
params[:service] = @service_url
|
196
|
+
params[:ticket] = @ticket if @ticket
|
197
|
+
params[:renew] = 'true' if @renew
|
198
|
+
params
|
199
|
+
end
|
123
200
|
|
124
201
|
def authenticated?
|
125
202
|
!!@user
|
126
203
|
end
|
127
204
|
|
128
|
-
def authenticate
|
129
|
-
response = CasResponseParser.parse(self, body)
|
205
|
+
def authenticate
|
206
|
+
response = CasResponseParser.parse(self, @body)
|
130
207
|
authenticated?
|
131
208
|
end
|
132
209
|
end
|
@@ -141,12 +218,19 @@ module Casablanca
|
|
141
218
|
end
|
142
219
|
end
|
143
220
|
|
221
|
+
##
|
222
|
+
# Monkey patches for URI::HTTP
|
144
223
|
class URI::HTTP
|
224
|
+
|
225
|
+
##
|
226
|
+
# Adds the hash to query
|
145
227
|
def merge_query(hash)
|
146
228
|
q = query ? query + '&' : ''
|
147
229
|
self.query = "#{q}#{hash_to_uri_array(hash)}"
|
148
230
|
end
|
149
231
|
|
232
|
+
private
|
233
|
+
|
150
234
|
def hash_to_uri_array(hash)
|
151
235
|
hash.collect do |name, value|
|
152
236
|
if value.kind_of? Array
|
@@ -1,55 +1,85 @@
|
|
1
1
|
module Casablanca
|
2
2
|
class RailsFilter
|
3
|
-
@@client = nil
|
4
3
|
|
5
4
|
class << self
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
|
5
|
+
|
6
|
+
##
|
7
|
+
# Configure the client
|
8
|
+
#
|
9
|
+
# Casablanca::RailsFilter.config do |config|
|
10
|
+
# config[:cas_server_url] = "http://localhost:4567"
|
11
|
+
# config[:service_url] = "http://localhost:3000"
|
12
|
+
# end
|
15
13
|
def config
|
16
14
|
config = {}
|
17
15
|
yield config
|
18
|
-
|
16
|
+
@cas_server_url = config[:cas_server_url]
|
17
|
+
@service_url = config[:service_url]
|
18
|
+
@renew = config[:renew] # always renew the session
|
19
|
+
# set logger to rails logger
|
20
|
+
Client.logger = ::ActionController::Base.logger
|
19
21
|
end
|
20
22
|
|
21
23
|
def filter(controller)
|
22
|
-
|
23
|
-
|
24
|
-
if
|
25
|
-
|
24
|
+
|
25
|
+
client = Client.new(:cas_server_url => @cas_server_url, :service_url => @service_url)
|
26
|
+
if !controller.session[:cas_user] && !controller.params[:ticket]
|
27
|
+
if renew?
|
28
|
+
logger.debug "Always require credentials for authentication"
|
29
|
+
else
|
30
|
+
logger.debug "Not authenticated yet. Ticket parameter required"
|
31
|
+
end
|
32
|
+
redirect_to_cas_login(controller, renew?)
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
ticket = Ticket.new(controller.params[:ticket], client.service_url, controller.session[:cas_renew])
|
36
|
+
if client.authenticate_ticket(ticket)
|
37
|
+
logger.debug "Ticket authenticated"
|
26
38
|
controller.session[:cas_user] = ticket.user
|
27
|
-
controller.session[:
|
39
|
+
controller.session[:cas_renew] = nil
|
28
40
|
return true
|
29
|
-
else
|
30
|
-
|
31
|
-
controller
|
32
|
-
|
33
|
-
controller
|
41
|
+
else
|
42
|
+
logger.warn "Ticket authentication failed: #{ticket.failure_message}"
|
43
|
+
logout(controller)
|
44
|
+
logger.debug "Renew login credentials"
|
45
|
+
redirect_to_cas_login(controller, true)
|
34
46
|
return false
|
35
47
|
end
|
36
48
|
end
|
37
49
|
|
38
|
-
|
39
|
-
|
50
|
+
##
|
51
|
+
# The login url of the Cas server. This page has the login form.
|
52
|
+
def login_url(params={})
|
53
|
+
client = Client.new(:cas_server_url => @cas_server_url, :service_url => @service_url)
|
54
|
+
client.login_url(params)
|
40
55
|
end
|
41
56
|
|
57
|
+
##
|
58
|
+
# The logout url of the Cas server.
|
59
|
+
def logout_url(params={})
|
60
|
+
client = Client.new(:cas_server_url => @cas_server_url, :service_url => @service_url)
|
61
|
+
client.logout_url(params)
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Logs out of the Cas server.
|
42
66
|
def logout(controller)
|
43
|
-
controller.
|
44
|
-
|
67
|
+
controller.session[:cas_user] = nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def logger
|
71
|
+
Client.logger
|
45
72
|
end
|
46
73
|
|
47
74
|
private
|
48
75
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
|
76
|
+
def redirect_to_cas_login(controller, renew)
|
77
|
+
controller.session[:cas_renew] = renew
|
78
|
+
controller.send(:redirect_to, login_url(:renew => renew))
|
79
|
+
end
|
80
|
+
|
81
|
+
def renew?
|
82
|
+
@renew
|
53
83
|
end
|
54
84
|
|
55
85
|
end
|
data/test/test_client.rb
CHANGED
@@ -18,7 +18,7 @@ class TestClient < Test::Unit::TestCase
|
|
18
18
|
def test_authenticate_ticket
|
19
19
|
service_ticket = get_service_ticket
|
20
20
|
@client = Client.new(:cas_server_url => "http://localhost:4567", :service_url => "http://localhost:3000")
|
21
|
-
mock_authenticate_ticket(VALID_REQUEST)
|
21
|
+
mock_authenticate_ticket(VALID_REQUEST)
|
22
22
|
@client.authenticate_ticket(service_ticket)
|
23
23
|
assert_equal 'admin', service_ticket.user
|
24
24
|
end
|
@@ -26,7 +26,7 @@ class TestClient < Test::Unit::TestCase
|
|
26
26
|
def test_validate_expired_ticket
|
27
27
|
mock_authenticate_ticket(INVALID_TICKET)
|
28
28
|
ticket = 'ST-1231341579r871C5757B79767C21E'
|
29
|
-
service_ticket = Ticket.new(ticket, 'http://localhost:3000'
|
29
|
+
service_ticket = Ticket.new(ticket, 'http://localhost:3000')
|
30
30
|
@client.authenticate_ticket(service_ticket)
|
31
31
|
assert_equal 'INVALID_TICKET', service_ticket.failure_code
|
32
32
|
#assert_equal "Ticket 'ST-1231341579r871C5757B79767C21E' has already been used up.", ticket.failure_message
|
@@ -35,7 +35,7 @@ class TestClient < Test::Unit::TestCase
|
|
35
35
|
def test_validate_invalid_ticket
|
36
36
|
mock_authenticate_ticket(INVALID_TICKET)
|
37
37
|
ticket = 'ST-1231242314r72465638160B31E8D1'
|
38
|
-
service_ticket = Ticket.new(ticket, 'http://localhost:3000'
|
38
|
+
service_ticket = Ticket.new(ticket, 'http://localhost:3000')
|
39
39
|
@client.authenticate_ticket(service_ticket)
|
40
40
|
assert_equal 'INVALID_TICKET', service_ticket.failure_code
|
41
41
|
assert_equal "Ticket ST-1231242314r72465638160B31E8D1 not recognized.", service_ticket.failure_message
|
@@ -49,13 +49,24 @@ class TestClient < Test::Unit::TestCase
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def test_login_url
|
52
|
-
assert_equal 'http://localhost:4567/login?service=http
|
52
|
+
assert_equal 'http://localhost:4567/login?service=http%3A%2F%2Flocalhost%3A3000', @client.login_url
|
53
53
|
end
|
54
54
|
|
55
|
+
def test_login_url_with_extra_params
|
56
|
+
url = @client.login_url(:renew => true)
|
57
|
+
assert_equal true, (url =~ /service\=http%3A%2F%2Flocalhost%3A3000/) > 0
|
58
|
+
assert_equal true, (url =~ /renew\=true/) > 0
|
59
|
+
end
|
60
|
+
|
55
61
|
def test_logout_url
|
56
|
-
assert_equal 'http://localhost:4567/logout', @client.logout_url
|
62
|
+
assert_equal 'http://localhost:4567/logout?', @client.logout_url
|
57
63
|
end
|
58
64
|
|
65
|
+
def test_logout_url_with_extra_params
|
66
|
+
url = @client.logout_url(:url => 'http://localhost:3000')
|
67
|
+
assert_equal true, (url =~ /url\=http%3A%2F%2Flocalhost%3A3000/) > 0
|
68
|
+
end
|
69
|
+
|
59
70
|
def test_validate_url
|
60
71
|
assert_equal 'http://localhost:4567/proxyValidate', @client.validate_url
|
61
72
|
end
|
@@ -68,17 +79,41 @@ class TestCommandLineClient < Test::Unit::TestCase
|
|
68
79
|
end
|
69
80
|
|
70
81
|
def test_login
|
71
|
-
mock_get_service_ticket
|
72
|
-
|
73
|
-
assert_equal '', res.body
|
74
|
-
assert_equal '303', res.code
|
75
|
-
assert_equal 0, res['location'] =~ /^http:\/\/localhost:3000\?ticket=ST-/
|
76
|
-
assert_equal
|
82
|
+
mock_get_service_ticket(@client)
|
83
|
+
service_ticket = @client.login('admin', 'admin')
|
84
|
+
#assert_equal '', res.body
|
85
|
+
#assert_equal '303', res.code
|
86
|
+
#assert_equal 0, res['location'] =~ /^http:\/\/localhost:3000\?ticket=ST-/
|
87
|
+
assert_equal 32, service_ticket.ticket.size
|
88
|
+
assert_equal 37, @client.ticket_granting_ticket.size
|
77
89
|
end
|
78
90
|
|
91
|
+
def test_logout
|
92
|
+
mock_get_service_ticket(@client)
|
93
|
+
service_ticket = @client.login('admin', 'admin')
|
94
|
+
assert_equal 37, @client.ticket_granting_ticket.size
|
95
|
+
# if MOCK_REQUESTS
|
96
|
+
# @client.expects(:get).returns(MockResponse.new(body, '200', :location => 'http://localhost:3000?ticket=ST-1231341579r871C5757B79767C21E'))
|
97
|
+
# end
|
98
|
+
service_ticket = @client.logout
|
99
|
+
assert_equal nil, @client.ticket_granting_ticket
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_logout_with_follow_url
|
103
|
+
mock_get_service_ticket(@client)
|
104
|
+
service_ticket = @client.login('admin', 'admin')
|
105
|
+
assert_equal 37, @client.ticket_granting_ticket.size
|
106
|
+
# if MOCK_REQUESTS
|
107
|
+
# @client.expects(:get).returns(MockResponse.new(body, '200', :location => 'http://localhost:3000?ticket=ST-1231341579r871C5757B79767C21E'))
|
108
|
+
# end
|
109
|
+
service_ticket = @client.logout('follow_url')
|
110
|
+
assert_equal nil, @client.ticket_granting_ticket
|
111
|
+
# TODO check for follow_url
|
112
|
+
end
|
113
|
+
|
79
114
|
def test_get_service_ticket
|
80
|
-
mock_get_service_ticket
|
81
|
-
ticket = @client.
|
115
|
+
mock_get_service_ticket(@client)
|
116
|
+
ticket = @client.login('admin', 'admin')
|
82
117
|
assert_equal 0, ticket.ticket =~ /^ST-/
|
83
118
|
assert_equal 32, ticket.ticket.size
|
84
119
|
end
|
data/test/test_helper.rb
CHANGED
@@ -12,22 +12,22 @@ class Test::Unit::TestCase
|
|
12
12
|
|
13
13
|
def mock_authenticate_ticket(body)
|
14
14
|
if MOCK_REQUESTS
|
15
|
-
|
15
|
+
Client.any_instance.expects(:get).returns(MockResponse.new(body, '200', :location => 'http://localhost:3000?ticket=ST-1231341579r871C5757B79767C21E'))
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def mock_get_service_ticket
|
19
|
+
def mock_get_service_ticket(client=Client.any_instance)
|
20
20
|
if MOCK_REQUESTS
|
21
|
-
|
21
|
+
client.expects(:post).returns(MockResponse.new('', '303', :location => 'http://localhost:3000?ticket=ST-1231341579r871C5757B79767C21E', :'set-cookie' => 'tgt=TGC-1232569033r763536CC6753E6F357'))
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
def get_service_ticket
|
26
26
|
cli = CommandLineClient.new(:cas_server_url => "http://localhost:4567", :service_url => "http://localhost:3000")
|
27
27
|
if MOCK_REQUESTS
|
28
|
-
cli.expects(:post).returns(MockResponse.new('', '303', :location => 'http://localhost:3000?ticket=ST-1231341579r871C5757B79767C21E'))
|
28
|
+
cli.expects(:post).returns(MockResponse.new('', '303', {:location => 'http://localhost:3000?ticket=ST-1231341579r871C5757B79767C21E', :'set-cookie' => 'tgt=TGC-1232569033r763536CC6753E6F357'}))
|
29
29
|
end
|
30
|
-
cli.
|
30
|
+
cli.login('admin', 'admin')
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
data/test/test_rails_filter.rb
CHANGED
@@ -1,73 +1,80 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'test_helper.rb')
|
2
|
-
|
2
|
+
|
3
3
|
class TestRailsFilter < Test::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
|
6
|
-
|
5
|
+
Casablanca::RailsFilter.config do |config|
|
6
|
+
config[:cas_server_url] = "http://localhost:4567"
|
7
|
+
config[:service_url] = "http://localhost:3000"
|
8
|
+
end
|
7
9
|
@controller = Controller.new
|
8
10
|
@controller.params = {}
|
9
11
|
end
|
10
12
|
|
11
13
|
def test_login_url
|
12
|
-
assert_equal 'http://localhost:4567/login?service=http
|
14
|
+
assert_equal 'http://localhost:4567/login?service=http%3A%2F%2Flocalhost%3A3000', RailsFilter.login_url
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_login_url_with_params
|
18
|
+
url = RailsFilter.login_url(:renew => true)
|
19
|
+
assert_equal true, (url =~ /service\=http%3A%2F%2Flocalhost%3A3000/) > 0
|
20
|
+
assert_equal true, (url =~ /renew\=true/) > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_logout_url
|
24
|
+
assert_equal 'http://localhost:4567/logout?', RailsFilter.logout_url
|
13
25
|
end
|
14
26
|
|
27
|
+
def test_logout
|
28
|
+
@controller.session = { :cas_user => 'admin' }
|
29
|
+
RailsFilter.logout(@controller)
|
30
|
+
assert_equal({:cas_user=>nil }, @controller.session)
|
31
|
+
end
|
32
|
+
|
15
33
|
def test_config
|
16
34
|
Casablanca::RailsFilter.config do |config|
|
17
35
|
config[:cas_server_url] = "http://example.com/cas_server"
|
18
36
|
config[:service_url] = "http://example.com/application"
|
19
37
|
end
|
20
|
-
assert_equal "http://example.com/cas_server", RailsFilter.client.cas_server_url
|
21
|
-
assert_equal "http://example.com/application", RailsFilter.client.service_url
|
22
|
-
|
23
|
-
# def test_filter_requires_config
|
24
|
-
# RailsFilter.config = nil
|
25
|
-
# assert_raises(RuntimeError) do
|
26
|
-
# RailsFilter.filter(Controller.new)
|
27
|
-
# end
|
28
|
-
# end
|
29
|
-
|
30
|
-
def test_logout
|
31
|
-
RailsFilter.logout(@controller)
|
32
|
-
assert_equal({}, @controller.session)
|
38
|
+
# assert_equal "http://example.com/cas_server", RailsFilter.client.cas_server_url
|
39
|
+
# assert_equal "http://example.com/application", RailsFilter.client.service_url
|
40
|
+
assert_equal 'http://example.com/cas_server/login?service=http%3A%2F%2Fexample.com%2Fapplication', RailsFilter.login_url
|
33
41
|
end
|
34
42
|
|
35
43
|
def test_filter_invalid_attempt
|
36
|
-
|
37
|
-
|
44
|
+
service_ticket = get_service_ticket
|
45
|
+
params = {:ticket => 'service_ticket.ticket'}
|
46
|
+
mock_authenticate_ticket(INVALID_REQUEST)
|
47
|
+
@controller.params = params
|
38
48
|
assert_equal false, RailsFilter.filter(@controller)
|
39
49
|
end
|
40
50
|
|
41
|
-
def
|
51
|
+
def test_filter_authenticated_with_valid_ticket_from_request
|
42
52
|
service_ticket = get_service_ticket
|
43
53
|
params = {:ticket => service_ticket.ticket}
|
44
54
|
mock_authenticate_ticket(VALID_REQUEST)
|
45
55
|
@controller.params = params
|
46
56
|
assert_equal true, RailsFilter.filter(@controller)
|
47
|
-
|
57
|
+
assert_equal 'admin', @controller.session[:cas_user]
|
48
58
|
end
|
49
59
|
|
50
|
-
def
|
51
|
-
|
52
|
-
@controller.session = {
|
53
|
-
|
60
|
+
def test_filter_already_authenticated_with_valid_ticket_from_session
|
61
|
+
service_ticket = get_service_ticket
|
62
|
+
@controller.session = {:cas_user => 'admin'}
|
63
|
+
mock_authenticate_ticket(VALID_REQUEST)
|
54
64
|
assert_equal true, RailsFilter.filter(@controller)
|
55
|
-
|
65
|
+
assert_equal 'admin', @controller.session[:cas_user]
|
56
66
|
end
|
57
67
|
|
58
|
-
|
59
|
-
mock_authenticate_ticket(INVALID_TICKET)
|
60
|
-
@controller.session[:cas_ticket] = { :ticket => 'a', :service_url => 'b' }
|
61
|
-
@controller.params = {:renew => true }
|
62
|
-
assert_equal false, RailsFilter.filter(@controller)
|
63
|
-
assert_session(nil, nil)
|
64
|
-
end
|
68
|
+
end
|
65
69
|
|
66
|
-
|
67
|
-
|
68
|
-
|
70
|
+
module ActionController
|
71
|
+
module Base
|
72
|
+
def self.logger
|
73
|
+
@logger = ::Logger.new($stderr)
|
74
|
+
@logger.level = ::Logger::ERROR
|
75
|
+
@logger
|
76
|
+
end
|
69
77
|
end
|
70
|
-
|
71
78
|
end
|
72
79
|
|
73
80
|
class Controller # < ActionController::Base
|
data/test/test_ticket.rb
CHANGED
@@ -23,7 +23,6 @@ class TestTicket < Test::Unit::TestCase
|
|
23
23
|
def test_from_hash
|
24
24
|
props = {:ticket => 'ticket',
|
25
25
|
:service_url => "http://localhost:3000",
|
26
|
-
:renew => 1,
|
27
26
|
:user => 'admin' }
|
28
27
|
ticket = Ticket.from_hash(props)
|
29
28
|
assert_equal props, ticket.to_hash
|
@@ -36,34 +35,31 @@ class TestTicket < Test::Unit::TestCase
|
|
36
35
|
assert_equal(expected, ticket.to_request_params)
|
37
36
|
end
|
38
37
|
|
39
|
-
def test_to_request_params_with_renew
|
40
|
-
ticket = Ticket.new('ticket', 'http://localhost:3000', true)
|
41
|
-
expected = {:ticket => 'ticket',
|
42
|
-
:service => "http://localhost:3000",
|
43
|
-
:renew => 1 }
|
44
|
-
assert_equal(expected, ticket.to_request_params)
|
45
|
-
end
|
46
|
-
|
47
38
|
def test_authenticate_valid_ticket
|
48
|
-
@ticket.
|
39
|
+
@ticket.body = VALID_REQUEST
|
40
|
+
@ticket.authenticate
|
49
41
|
assert_equal 'admin', @ticket.user
|
50
42
|
end
|
51
43
|
|
52
44
|
def test_authenticate_invalid_request_resets_ticket_to_unauthenticated
|
53
|
-
@ticket.
|
45
|
+
@ticket.body = VALID_REQUEST
|
46
|
+
@ticket.authenticate
|
54
47
|
assert_equal true, @ticket.authenticated?
|
55
|
-
@ticket.
|
48
|
+
@ticket.body = INVALID_REQUEST
|
49
|
+
@ticket.authenticate
|
56
50
|
assert_equal false, @ticket.authenticated?
|
57
51
|
end
|
58
52
|
|
59
53
|
def test_authenticate_invalid_request
|
60
|
-
@ticket.
|
54
|
+
@ticket.body = INVALID_REQUEST
|
55
|
+
@ticket.authenticate
|
61
56
|
assert_equal 'INVALID_REQUEST', @ticket.failure_code
|
62
57
|
assert_equal 'Ticket or service parameter was missing in the request.', @ticket.failure_message
|
63
58
|
end
|
64
59
|
|
65
60
|
def test_authenticate_invalid_ticket
|
66
|
-
@ticket.
|
61
|
+
@ticket.body = INVALID_TICKET
|
62
|
+
@ticket.authenticate
|
67
63
|
assert_equal 'INVALID_TICKET', @ticket.failure_code
|
68
64
|
assert_equal 'Ticket ST-1231242314r72465638160B31E8D1 not recognized.', @ticket.failure_message
|
69
65
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: casablanca
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- FIX
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-24 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,9 +20,9 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 1.8.
|
23
|
+
version: 1.8.3
|
24
24
|
version:
|
25
|
-
description:
|
25
|
+
description: Casablanca is a single sign-on client for the CAS 2.0 protocol.
|
26
26
|
email:
|
27
27
|
- FIX@example.com
|
28
28
|
executables:
|
@@ -32,10 +32,11 @@ extensions: []
|
|
32
32
|
extra_rdoc_files:
|
33
33
|
- History.txt
|
34
34
|
- Manifest.txt
|
35
|
+
- README.txt
|
35
36
|
files:
|
36
37
|
- History.txt
|
37
38
|
- Manifest.txt
|
38
|
-
- README.
|
39
|
+
- README.txt
|
39
40
|
- Rakefile
|
40
41
|
- init.rb
|
41
42
|
- bin/casablanca
|
@@ -75,7 +76,7 @@ rubyforge_project: casablanca
|
|
75
76
|
rubygems_version: 1.2.0
|
76
77
|
signing_key:
|
77
78
|
specification_version: 2
|
78
|
-
summary:
|
79
|
+
summary: Casablanca is a single sign-on client for the CAS 2.0 protocol.
|
79
80
|
test_files:
|
80
81
|
- test/test_client.rb
|
81
82
|
- test/test_helper.rb
|