rubycas-client-rails 0.1.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.
- data/MIT-LICENSE +20 -0
- data/README.markdown +43 -0
- data/Rakefile +23 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/lib/rubycas-client-rails.rb +424 -0
- data/rubycas-client-rails.gemspec +18 -0
- data/uninstall.rb +1 -0
- metadata +106 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 University of Toronto
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
RubyCAS-Client-Rails
|
2
|
+
====================
|
3
|
+
|
4
|
+
Rails plugin for using the RubyCAS-Client as a controller filter.
|
5
|
+
|
6
|
+
This uses a Railtie, so will only work with Rails 3.0 and up.
|
7
|
+
|
8
|
+
|
9
|
+
Example
|
10
|
+
=======
|
11
|
+
|
12
|
+
First, install the `rubycas-client` gem:
|
13
|
+
|
14
|
+
gem install rubycas-client
|
15
|
+
|
16
|
+
Next, clone the `rubycas-client-rails` code from Github (this will eventually
|
17
|
+
be released as a gem too).
|
18
|
+
|
19
|
+
Now add both to your `Gemfile`:
|
20
|
+
|
21
|
+
gem 'rubycas-client'
|
22
|
+
gem 'rubycas-client-rails', :path => '/path/where/you/cloned/rubycas-client-rails'
|
23
|
+
|
24
|
+
In your `application.rb` add:
|
25
|
+
|
26
|
+
config.rubycas.cas_base_url = 'https://cas.example.com/'
|
27
|
+
|
28
|
+
Finally, to enable the CAS filter for a controller:
|
29
|
+
|
30
|
+
class MyController < ApplicationController
|
31
|
+
|
32
|
+
before_filter RubyCAS::Filter
|
33
|
+
|
34
|
+
Many other configuration options are available. For example you can instruct
|
35
|
+
the client to log its actions to the default Rails logger using:
|
36
|
+
|
37
|
+
config.rubycas.logger = Rails.logger
|
38
|
+
|
39
|
+
See the (outdated) documentation at [http://rubycas-client.rubyforge.org/](http://rubycas-client.rubyforge.org/)
|
40
|
+
for a full list of config options.
|
41
|
+
|
42
|
+
|
43
|
+
Copyright (c) 2011 University of Toronto, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the rubycas_client_rails plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.libs << 'test'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate documentation for the rubycas_client_rails plugin.'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'RubycasClientRails'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Include hook code here
|
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
@@ -0,0 +1,424 @@
|
|
1
|
+
|
2
|
+
require 'casclient'
|
3
|
+
|
4
|
+
module RubyCAS
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
config.rubycas = ActiveSupport::OrderedOptions.new
|
7
|
+
|
8
|
+
initializer 'rubycas.initialize' do |app|
|
9
|
+
RubyCAS::Filter.setup(config.rubycas)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Filter
|
14
|
+
cattr_reader :config, :log, :client
|
15
|
+
|
16
|
+
# These are initialized when you call setup.
|
17
|
+
@@client = nil
|
18
|
+
@@log = nil
|
19
|
+
@@fake_user = nil
|
20
|
+
@@fake_extra_attributes = nil
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def setup(config)
|
24
|
+
@@config = config
|
25
|
+
@@config[:logger] = Rails.logger unless @@config[:logger]
|
26
|
+
@@client = CASClient::Client.new(@@config)
|
27
|
+
@@log = @@client.log
|
28
|
+
end
|
29
|
+
|
30
|
+
def filter(controller)
|
31
|
+
raise "Cannot use the CASClient filter because it has not yet been configured." if config.nil?
|
32
|
+
|
33
|
+
if @@fake_user
|
34
|
+
controller.session[client.username_session_key] = @@fake_user
|
35
|
+
controller.session[:casfilteruser] = @@fake_user
|
36
|
+
controller.session[client.extra_attributes_session_key] = @@fake_extra_attributes
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
last_st = controller.session[:cas_last_valid_ticket]
|
42
|
+
|
43
|
+
if single_sign_out(controller)
|
44
|
+
controller.send(:render, :text => "CAS Single-Sign-Out request intercepted.")
|
45
|
+
return false
|
46
|
+
end
|
47
|
+
|
48
|
+
st = read_ticket(controller)
|
49
|
+
|
50
|
+
is_new_session = true
|
51
|
+
|
52
|
+
if st && last_st &&
|
53
|
+
last_st.ticket == st.ticket &&
|
54
|
+
last_st.service == st.service
|
55
|
+
# warn() rather than info() because we really shouldn't be re-validating the same ticket.
|
56
|
+
# The only situation where this is acceptable is if the user manually does a refresh and
|
57
|
+
# the same ticket happens to be in the URL.
|
58
|
+
log.warn("Re-using previously validated ticket since the ticket id and service are the same.")
|
59
|
+
st = last_st
|
60
|
+
is_new_session = false
|
61
|
+
elsif last_st &&
|
62
|
+
!config[:authenticate_on_every_request] &&
|
63
|
+
controller.session[client.username_session_key]
|
64
|
+
# Re-use the previous ticket if the user already has a local CAS session (i.e. if they were already
|
65
|
+
# previously authenticated for this service). This is to prevent redirection to the CAS server on every
|
66
|
+
# request.
|
67
|
+
#
|
68
|
+
# This behaviour can be disabled (so that every request is routed through the CAS server) by setting
|
69
|
+
# the :authenticate_on_every_request config option to true. However, this is not desirable since
|
70
|
+
# it will almost certainly break POST request, AJAX calls, etc.
|
71
|
+
log.debug "Existing local CAS session detected for #{controller.session[client.username_session_key].inspect}. "+
|
72
|
+
"Previous ticket #{last_st.ticket.inspect} will be re-used."
|
73
|
+
st = last_st
|
74
|
+
is_new_session = false
|
75
|
+
end
|
76
|
+
|
77
|
+
if st
|
78
|
+
client.validate_service_ticket(st) unless st.has_been_validated?
|
79
|
+
vr = st.response
|
80
|
+
|
81
|
+
if st.is_valid?
|
82
|
+
if is_new_session
|
83
|
+
log.info("Ticket #{st.ticket.inspect} for service #{st.service.inspect} belonging to user #{vr.user.inspect} is VALID.")
|
84
|
+
controller.session[client.username_session_key] = vr.user.dup
|
85
|
+
controller.session[client.extra_attributes_session_key] = HashWithIndifferentAccess.new(vr.extra_attributes) if vr.extra_attributes
|
86
|
+
|
87
|
+
if vr.extra_attributes
|
88
|
+
log.debug("Extra user attributes provided along with ticket #{st.ticket.inspect}: #{vr.extra_attributes.inspect}.")
|
89
|
+
end
|
90
|
+
|
91
|
+
# RubyCAS-Client 1.x used :casfilteruser as it's username session key,
|
92
|
+
# so we need to set this here to ensure compatibility with configurations
|
93
|
+
# built around the old client.
|
94
|
+
controller.session[:casfilteruser] = vr.user
|
95
|
+
|
96
|
+
if config[:enable_single_sign_out]
|
97
|
+
f = store_service_session_lookup(st, controller.request.session_options[:id] || controller.session.session_id)
|
98
|
+
log.debug("Wrote service session lookup file to #{f.inspect} with session id #{controller.request.session_options[:id] || controller.session.session_id.inspect}.")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Store the ticket in the session to avoid re-validating the same service
|
103
|
+
# ticket with the CAS server.
|
104
|
+
controller.session[:cas_last_valid_ticket] = st
|
105
|
+
|
106
|
+
if vr.pgt_iou
|
107
|
+
unless controller.session[:cas_pgt] && controller.session[:cas_pgt].ticket && controller.session[:cas_pgt].iou == vr.pgt_iou
|
108
|
+
log.info("Receipt has a proxy-granting ticket IOU. Attempting to retrieve the proxy-granting ticket...")
|
109
|
+
pgt = client.retrieve_proxy_granting_ticket(vr.pgt_iou)
|
110
|
+
|
111
|
+
if pgt
|
112
|
+
log.debug("Got PGT #{pgt.ticket.inspect} for PGT IOU #{pgt.iou.inspect}. This will be stored in the session.")
|
113
|
+
controller.session[:cas_pgt] = pgt
|
114
|
+
# For backwards compatibility with RubyCAS-Client 1.x configurations...
|
115
|
+
controller.session[:casfilterpgt] = pgt
|
116
|
+
else
|
117
|
+
log.error("Failed to retrieve a PGT for PGT IOU #{vr.pgt_iou}!")
|
118
|
+
end
|
119
|
+
else
|
120
|
+
log.info("PGT is present in session and PGT IOU #{vr.pgt_iou} matches the saved PGT IOU. Not retrieving new PGT.")
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
return true
|
126
|
+
else
|
127
|
+
log.warn("Ticket #{st.ticket.inspect} failed validation -- #{vr.failure_code}: #{vr.failure_message}")
|
128
|
+
unauthorized!(controller, vr)
|
129
|
+
return false
|
130
|
+
end
|
131
|
+
else # no service ticket was present in the request
|
132
|
+
if returning_from_gateway?(controller)
|
133
|
+
log.info "Returning from CAS gateway without authentication."
|
134
|
+
|
135
|
+
# unset, to allow for the next request to be authenticated if necessary
|
136
|
+
controller.session[:cas_sent_to_gateway] = false
|
137
|
+
|
138
|
+
if use_gatewaying?
|
139
|
+
log.info "This CAS client is configured to use gatewaying, so we will permit the user to continue without authentication."
|
140
|
+
controller.session[client.username_session_key] = nil
|
141
|
+
return true
|
142
|
+
else
|
143
|
+
log.warn "The CAS client is NOT configured to allow gatewaying, yet this request was gatewayed. Something is not right!"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
unauthorized!(controller)
|
148
|
+
return false
|
149
|
+
end
|
150
|
+
rescue OpenSSL::SSL::SSLError
|
151
|
+
log.error("SSL Error: hostname was not match with the server certificate. You can try to disable the ssl verification with a :force_ssl_verification => false in your configurations file.")
|
152
|
+
unauthorized!(controller)
|
153
|
+
return false
|
154
|
+
end
|
155
|
+
|
156
|
+
# used to allow faking for testing
|
157
|
+
# with cucumber and other tools.
|
158
|
+
# use like
|
159
|
+
# CASClient::Frameworks::Rails::Filter.fake("homer")
|
160
|
+
# you can also fake extra attributes by including a second parameter
|
161
|
+
# CASClient::Frameworks::Rails::Filter.fake("homer", {:roles => ['dad', 'husband']})
|
162
|
+
def fake(username, extra_attributes = nil)
|
163
|
+
@@fake_user = username
|
164
|
+
@@fake_extra_attributes = extra_attributes
|
165
|
+
end
|
166
|
+
|
167
|
+
def use_gatewaying?
|
168
|
+
@@config[:use_gatewaying]
|
169
|
+
end
|
170
|
+
|
171
|
+
# Returns the login URL for the current controller.
|
172
|
+
# Useful when you want to provide a "Login" link in a GatewayFilter'ed
|
173
|
+
# action.
|
174
|
+
def login_url(controller)
|
175
|
+
service_url = read_service_url(controller)
|
176
|
+
url = client.add_service_to_login_url(service_url)
|
177
|
+
log.debug("Generated login url: #{url}")
|
178
|
+
return url
|
179
|
+
end
|
180
|
+
|
181
|
+
# allow controllers to reuse the existing config to auto-login to
|
182
|
+
# the service
|
183
|
+
#
|
184
|
+
# Use this from within a controller. Pass the controller, the
|
185
|
+
# login-credentials and the path that you want the user
|
186
|
+
# resdirected to on success.
|
187
|
+
#
|
188
|
+
# When writing a login-action you must check the return-value of
|
189
|
+
# the response to see if it failed!
|
190
|
+
#
|
191
|
+
# If it worked - you need to redirect the user to the service -
|
192
|
+
# path, because that has the ticket that will *actually* log them
|
193
|
+
# into your system
|
194
|
+
#
|
195
|
+
# example:
|
196
|
+
# def autologin
|
197
|
+
# resp = CASClient::Frameworks::Rails::Filter.login_to_service(self, credentials, dashboard_url)
|
198
|
+
# if resp.is_faiulure?
|
199
|
+
# flash[:error] = 'Login failed'
|
200
|
+
# render :action => 'login'
|
201
|
+
# else
|
202
|
+
# return redirect_to(@resp.service_redirect_url)
|
203
|
+
# end
|
204
|
+
# end
|
205
|
+
def login_to_service(controller, credentials, return_path)
|
206
|
+
resp = @@client.login_to_service(credentials, return_path)
|
207
|
+
if resp.is_failure?
|
208
|
+
log.info("Validation failed for service #{return_path.inspect} reason: '#{resp.failure_message}'")
|
209
|
+
else
|
210
|
+
log.info("Ticket #{resp.ticket.inspect} for service #{return_path.inspect} is VALID.")
|
211
|
+
end
|
212
|
+
|
213
|
+
resp
|
214
|
+
end
|
215
|
+
|
216
|
+
# Clears the given controller's local Rails session, does some local
|
217
|
+
# CAS cleanup, and redirects to the CAS logout page. Additionally, the
|
218
|
+
# <tt>request.referer</tt> value from the <tt>controller</tt> instance
|
219
|
+
# is passed to the CAS server as a 'destination' parameter. This
|
220
|
+
# allows RubyCAS server to provide a follow-up login page allowing
|
221
|
+
# the user to log back in to the service they just logged out from
|
222
|
+
# using a different username and password. Other CAS server
|
223
|
+
# implemenations may use this 'destination' parameter in different
|
224
|
+
# ways.
|
225
|
+
# If given, the optional <tt>service</tt> URL overrides
|
226
|
+
# <tt>request.referer</tt>.
|
227
|
+
def logout(controller, service = nil)
|
228
|
+
referer = service || controller.request.referer
|
229
|
+
st = controller.session[:cas_last_valid_ticket]
|
230
|
+
delete_service_session_lookup(st) if st
|
231
|
+
controller.send(:reset_session)
|
232
|
+
controller.send(:redirect_to, client.logout_url(referer))
|
233
|
+
end
|
234
|
+
|
235
|
+
def unauthorized!(controller, vr = nil)
|
236
|
+
if controller.params[:format] == "xml"
|
237
|
+
if vr
|
238
|
+
controller.send(:render, :xml => "<errors><error>#{vr.failure_message}</error></errors>", :status => 401)
|
239
|
+
else
|
240
|
+
controller.send(:head, 401)
|
241
|
+
end
|
242
|
+
else
|
243
|
+
redirect_to_cas_for_authentication(controller)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def redirect_to_cas_for_authentication(controller)
|
248
|
+
redirect_url = login_url(controller)
|
249
|
+
|
250
|
+
if use_gatewaying?
|
251
|
+
controller.session[:cas_sent_to_gateway] = true
|
252
|
+
redirect_url << "&gateway=true"
|
253
|
+
else
|
254
|
+
controller.session[:cas_sent_to_gateway] = false
|
255
|
+
end
|
256
|
+
|
257
|
+
if controller.session[:previous_redirect_to_cas] &&
|
258
|
+
controller.session[:previous_redirect_to_cas] > (Time.now - 1.second)
|
259
|
+
log.warn("Previous redirect to the CAS server was less than a second ago. The client at #{controller.request.remote_ip.inspect} may be stuck in a redirection loop!")
|
260
|
+
controller.session[:cas_validation_retry_count] ||= 0
|
261
|
+
|
262
|
+
if controller.session[:cas_validation_retry_count] > 3
|
263
|
+
log.error("Redirection loop intercepted. Client at #{controller.request.remote_ip.inspect} will be redirected back to login page and forced to renew authentication.")
|
264
|
+
redirect_url += "&renew=1&redirection_loop_intercepted=1"
|
265
|
+
end
|
266
|
+
|
267
|
+
controller.session[:cas_validation_retry_count] += 1
|
268
|
+
else
|
269
|
+
controller.session[:cas_validation_retry_count] = 0
|
270
|
+
end
|
271
|
+
controller.session[:previous_redirect_to_cas] = Time.now
|
272
|
+
|
273
|
+
log.debug("Redirecting to #{redirect_url.inspect}")
|
274
|
+
controller.send(:redirect_to, redirect_url)
|
275
|
+
end
|
276
|
+
|
277
|
+
private
|
278
|
+
def single_sign_out(controller)
|
279
|
+
|
280
|
+
# Avoid calling raw_post (which may consume the post body) if
|
281
|
+
# this seems to be a file upload
|
282
|
+
if content_type = controller.request.headers["CONTENT_TYPE"] &&
|
283
|
+
content_type =~ %r{^multipart/}
|
284
|
+
return false
|
285
|
+
end
|
286
|
+
|
287
|
+
if controller.request.post? &&
|
288
|
+
controller.params['logoutRequest'] &&
|
289
|
+
controller.params['logoutRequest'] =~
|
290
|
+
%r{^<samlp:LogoutRequest.*?<samlp:SessionIndex>(.*)</samlp:SessionIndex>}m
|
291
|
+
# TODO: Maybe check that the request came from the registered CAS server? Although this might be
|
292
|
+
# pointless since it's easily spoofable...
|
293
|
+
si = $~[1]
|
294
|
+
|
295
|
+
unless config[:enable_single_sign_out]
|
296
|
+
log.warn "Ignoring single-sign-out request for CAS session #{si.inspect} because ssout functionality is not enabled (see the :enable_single_sign_out config option)."
|
297
|
+
return false
|
298
|
+
end
|
299
|
+
|
300
|
+
log.debug "Intercepted single-sign-out request for CAS session #{si.inspect}."
|
301
|
+
|
302
|
+
begin
|
303
|
+
required_sess_store = ActiveRecord::SessionStore
|
304
|
+
current_sess_store = ActionController::Base.session_store
|
305
|
+
rescue NameError
|
306
|
+
# for older versions of Rails (prior to 2.3)
|
307
|
+
required_sess_store = CGI::Session::ActiveRecordStore
|
308
|
+
current_sess_store = ActionController::Base.session_options[:database_manager]
|
309
|
+
end
|
310
|
+
|
311
|
+
|
312
|
+
if current_sess_store == required_sess_store
|
313
|
+
session_id = read_service_session_lookup(si)
|
314
|
+
|
315
|
+
if session_id
|
316
|
+
session = current_sess_store::Session.find_by_session_id(session_id)
|
317
|
+
if session
|
318
|
+
session.destroy
|
319
|
+
log.debug("Destroyed #{session.inspect} for session #{session_id.inspect} corresponding to service ticket #{si.inspect}.")
|
320
|
+
else
|
321
|
+
log.debug("Data for session #{session_id.inspect} was not found. It may have already been cleared by a local CAS logout request.")
|
322
|
+
end
|
323
|
+
|
324
|
+
log.info("Single-sign-out for session #{session_id.inspect} completed successfuly.")
|
325
|
+
else
|
326
|
+
log.warn("Couldn't destroy session with SessionIndex #{si} because no corresponding session id could be looked up.")
|
327
|
+
end
|
328
|
+
else
|
329
|
+
log.error "Cannot process logout request because this Rails application's session store is "+
|
330
|
+
" #{current_sess_store.name.inspect}. Single Sign-Out only works with the "+
|
331
|
+
" #{required_sess_store.name.inspect} session store."
|
332
|
+
end
|
333
|
+
|
334
|
+
# Return true to indicate that a single-sign-out request was detected
|
335
|
+
# and that further processing of the request is unnecessary.
|
336
|
+
return true
|
337
|
+
end
|
338
|
+
|
339
|
+
# This is not a single-sign-out request.
|
340
|
+
return false
|
341
|
+
end
|
342
|
+
|
343
|
+
def read_ticket(controller)
|
344
|
+
# Note that we are now deleting the 'ticket' and 'renew' parameters, since they really
|
345
|
+
# have no business getting passed on to the controller action.
|
346
|
+
|
347
|
+
ticket = controller.params.delete(:ticket)
|
348
|
+
|
349
|
+
return nil unless ticket
|
350
|
+
|
351
|
+
log.debug("Request contains ticket #{ticket.inspect}.")
|
352
|
+
|
353
|
+
if ticket =~ /^PT-/
|
354
|
+
CASClient::ProxyTicket.new(ticket, read_service_url(controller), controller.params.delete(:renew))
|
355
|
+
else
|
356
|
+
CASClient::ServiceTicket.new(ticket, read_service_url(controller), controller.params.delete(:renew))
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
def returning_from_gateway?(controller)
|
361
|
+
controller.session[:cas_sent_to_gateway]
|
362
|
+
end
|
363
|
+
|
364
|
+
def read_service_url(controller)
|
365
|
+
if config[:service_url]
|
366
|
+
log.debug("Using explicitly set service url: #{config[:service_url]}")
|
367
|
+
return config[:service_url]
|
368
|
+
end
|
369
|
+
|
370
|
+
params = controller.params.dup
|
371
|
+
params.delete(:ticket)
|
372
|
+
service_url = controller.url_for(params)
|
373
|
+
log.debug("Guessed service url: #{service_url.inspect}")
|
374
|
+
return service_url
|
375
|
+
end
|
376
|
+
|
377
|
+
# Creates a file in tmp/sessions linking a SessionTicket
|
378
|
+
# with the local Rails session id. The file is named
|
379
|
+
# cas_sess.<session ticket> and its text contents is the corresponding
|
380
|
+
# Rails session id.
|
381
|
+
# Returns the filename of the lookup file created.
|
382
|
+
def store_service_session_lookup(st, sid)
|
383
|
+
st = st.ticket if st.kind_of? CASClient::ServiceTicket
|
384
|
+
f = File.new(filename_of_service_session_lookup(st), 'w')
|
385
|
+
f.write(sid)
|
386
|
+
f.close
|
387
|
+
return f.path
|
388
|
+
end
|
389
|
+
|
390
|
+
# Returns the local Rails session ID corresponding to the given
|
391
|
+
# ServiceTicket. This is done by reading the contents of the
|
392
|
+
# cas_sess.<session ticket> file created in a prior call to
|
393
|
+
# #store_service_session_lookup.
|
394
|
+
def read_service_session_lookup(st)
|
395
|
+
st = st.ticket if st.kind_of? CASClient::ServiceTicket
|
396
|
+
ssl_filename = filename_of_service_session_lookup(st)
|
397
|
+
return File.exists?(ssl_filename) && IO.read(ssl_filename)
|
398
|
+
end
|
399
|
+
|
400
|
+
# Removes a stored relationship between a ServiceTicket and a local
|
401
|
+
# Rails session id. This should be called when the session is being
|
402
|
+
# closed.
|
403
|
+
#
|
404
|
+
# See #store_service_session_lookup.
|
405
|
+
def delete_service_session_lookup(st)
|
406
|
+
st = st.ticket if st.kind_of? CASClient::ServiceTicket
|
407
|
+
ssl_filename = filename_of_service_session_lookup(st)
|
408
|
+
File.delete(ssl_filename) if File.exists?(ssl_filename)
|
409
|
+
end
|
410
|
+
|
411
|
+
# Returns the path and filename of the service session lookup file.
|
412
|
+
def filename_of_service_session_lookup(st)
|
413
|
+
st = st.ticket if st.kind_of? CASClient::ServiceTicket
|
414
|
+
return "#{Rails.root}/tmp/sessions/cas_sess.#{st}"
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
class GatewayFilter < Filter
|
419
|
+
def self.use_gatewaying?
|
420
|
+
return true unless @@config[:use_gatewaying] == false
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{rubycas-client-rails}
|
3
|
+
s.version = "0.1.0"
|
4
|
+
|
5
|
+
s.authors = ["Matt Zukowski"]
|
6
|
+
s.date = %q{2011-08-13}
|
7
|
+
s.description = %q{Rails plugin for using the RubyCAS-Client as a controller filter.}
|
8
|
+
s.summary = %q{RubyCAS-Client Railtie for Rails 3.0.}
|
9
|
+
s.email = %q{matt dot zukowski at utoronto dot ca}
|
10
|
+
s.files = `git ls-files`.split("\n")
|
11
|
+
s.homepage = %q{http://rubycas-client.rubyforge.org}
|
12
|
+
s.rdoc_options = ["--main", "README.txt"]
|
13
|
+
s.require_paths = ["lib"]
|
14
|
+
s.rubyforge_project = %q{rubycas-client}
|
15
|
+
|
16
|
+
s.add_dependency('rails', '>= 3.0.0')
|
17
|
+
s.add_dependency('rubycas-client', '>= 2.2.0')
|
18
|
+
end
|
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubycas-client-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Matt Zukowski
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-08-13 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rails
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
version: 3.0.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rubycas-client
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 7
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 2
|
49
|
+
- 0
|
50
|
+
version: 2.2.0
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
description: Rails plugin for using the RubyCAS-Client as a controller filter.
|
54
|
+
email: matt dot zukowski at utoronto dot ca
|
55
|
+
executables: []
|
56
|
+
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
extra_rdoc_files: []
|
60
|
+
|
61
|
+
files:
|
62
|
+
- MIT-LICENSE
|
63
|
+
- README.markdown
|
64
|
+
- Rakefile
|
65
|
+
- init.rb
|
66
|
+
- install.rb
|
67
|
+
- lib/rubycas-client-rails.rb
|
68
|
+
- rubycas-client-rails.gemspec
|
69
|
+
- uninstall.rb
|
70
|
+
has_rdoc: true
|
71
|
+
homepage: http://rubycas-client.rubyforge.org
|
72
|
+
licenses: []
|
73
|
+
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options:
|
76
|
+
- --main
|
77
|
+
- README.txt
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
requirements: []
|
99
|
+
|
100
|
+
rubyforge_project: rubycas-client
|
101
|
+
rubygems_version: 1.4.2
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: RubyCAS-Client Railtie for Rails 3.0.
|
105
|
+
test_files: []
|
106
|
+
|