vibes-rubycas-client 2.3.0.alpha
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/.rvmrc +1 -0
- data/.source_index +0 -0
- data/CHANGELOG.txt +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +22 -0
- data/History.txt +192 -0
- data/LICENSE.txt +26 -0
- data/README.rdoc +321 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/examples/merb/.gitignore +18 -0
- data/examples/merb/README.textile +12 -0
- data/examples/merb/Rakefile +35 -0
- data/examples/merb/merb.thor +2020 -0
- data/examples/merb/merb_auth_cas.rb +67 -0
- data/examples/merb/spec/spec_helper.rb +24 -0
- data/examples/rails/README +16 -0
- data/examples/rails/app/controllers/advanced_example_controller.rb +31 -0
- data/examples/rails/app/controllers/application.rb +2 -0
- data/examples/rails/app/controllers/simple_example_controller.rb +16 -0
- data/examples/rails/app/views/advanced_example/index.html.erb +13 -0
- data/examples/rails/app/views/advanced_example/my_account.html.erb +11 -0
- data/examples/rails/app/views/simple_example/index.html.erb +6 -0
- data/examples/rails/config/boot.rb +109 -0
- data/examples/rails/config/environment.rb +39 -0
- data/examples/rails/config/environments/development.rb +17 -0
- data/examples/rails/config/environments/production.rb +22 -0
- data/examples/rails/config/environments/test.rb +22 -0
- data/examples/rails/config/initializers/inflections.rb +10 -0
- data/examples/rails/config/initializers/mime_types.rb +5 -0
- data/examples/rails/config/initializers/new_rails_defaults.rb +17 -0
- data/examples/rails/config/routes.rb +4 -0
- data/examples/rails/log/development.log +946 -0
- data/examples/rails/log/production.log +0 -0
- data/examples/rails/log/server.log +0 -0
- data/examples/rails/log/test.log +0 -0
- data/examples/rails/script/about +4 -0
- data/examples/rails/script/console +3 -0
- data/examples/rails/script/server +3 -0
- data/lib/casclient.rb +89 -0
- data/lib/casclient/client.rb +271 -0
- data/lib/casclient/frameworks/merb/filter.rb +105 -0
- data/lib/casclient/frameworks/merb/strategy.rb +110 -0
- data/lib/casclient/frameworks/rails/cas_proxy_callback_controller.rb +76 -0
- data/lib/casclient/frameworks/rails/filter.rb +415 -0
- data/lib/casclient/responses.rb +197 -0
- data/lib/casclient/tickets.rb +38 -0
- data/lib/vibes-rubycas-client.rb +1 -0
- data/vibes-rubycas-client.gemspec +100 -0
- metadata +198 -0
File without changes
|
File without changes
|
File without changes
|
data/lib/casclient.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'cgi'
|
3
|
+
require 'logger'
|
4
|
+
require 'net/https'
|
5
|
+
require 'rexml/document'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'active_support'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rubygems'
|
11
|
+
require 'active_support'
|
12
|
+
end
|
13
|
+
|
14
|
+
$: << File.expand_path(File.dirname(__FILE__))
|
15
|
+
|
16
|
+
module CASClient
|
17
|
+
class CASException < Exception
|
18
|
+
end
|
19
|
+
|
20
|
+
# Customized logger for the client.
|
21
|
+
# This is useful if you're trying to do logging in Rails, since Rails'
|
22
|
+
# clean_logger.rb pretty much completely breaks the base Logger class.
|
23
|
+
class Logger < ::Logger
|
24
|
+
def initialize(logdev, shift_age = 0, shift_size = 1048576)
|
25
|
+
@default_formatter = Formatter.new
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def format_message(severity, datetime, progrname, msg)
|
30
|
+
(@formatter || @default_formatter).call(severity, datetime, progname, msg)
|
31
|
+
end
|
32
|
+
|
33
|
+
def break
|
34
|
+
self << $/
|
35
|
+
end
|
36
|
+
|
37
|
+
class Formatter < ::Logger::Formatter
|
38
|
+
Format = "[%s#%d] %5s -- %s: %s\n"
|
39
|
+
|
40
|
+
def call(severity, time, progname, msg)
|
41
|
+
Format % [format_datetime(time), $$, severity, progname, msg2str(msg)]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Wraps a real Logger. If no real Logger is set, then this wrapper
|
47
|
+
# will quietly swallow any logging calls.
|
48
|
+
class LoggerWrapper
|
49
|
+
def initialize(real_logger=nil)
|
50
|
+
set_logger(real_logger)
|
51
|
+
end
|
52
|
+
# Assign the 'real' Logger instance that this dummy instance wraps around.
|
53
|
+
def set_real_logger(real_logger)
|
54
|
+
@real_logger = real_logger
|
55
|
+
end
|
56
|
+
# Log using the appropriate method if we have a logger
|
57
|
+
# if we dont' have a logger, gracefully ignore.
|
58
|
+
def method_missing(name, *args)
|
59
|
+
if @real_logger && @real_logger.respond_to?(name)
|
60
|
+
@real_logger.send(name, *args)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
require 'casclient/tickets'
|
67
|
+
require 'casclient/responses'
|
68
|
+
require 'casclient/client'
|
69
|
+
|
70
|
+
# Detect legacy configuration and show appropriate error message
|
71
|
+
module CAS
|
72
|
+
module Filter
|
73
|
+
class << self
|
74
|
+
def method_missing(method, *args)
|
75
|
+
$stderr.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
76
|
+
$stderr.puts
|
77
|
+
$stderr.puts "WARNING: Your RubyCAS-Client configuration is no longer valid!!"
|
78
|
+
$stderr.puts
|
79
|
+
$stderr.puts "For information on the new configuration format please see: "
|
80
|
+
$stderr.puts
|
81
|
+
$stderr.puts " http://rubycas-client.googlecode.com/svn/trunk/rubycas-client/README.txt"
|
82
|
+
$stderr.puts
|
83
|
+
$stderr.puts "After upgrading your configuration you should also clear your application's session store."
|
84
|
+
$stderr.puts
|
85
|
+
$stderr.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,271 @@
|
|
1
|
+
module CASClient
|
2
|
+
# The client brokers all HTTP transactions with the CAS server.
|
3
|
+
class Client
|
4
|
+
attr_reader :cas_base_url
|
5
|
+
attr_reader :log, :username_session_key, :extra_attributes_session_key
|
6
|
+
attr_writer :login_url, :validate_url, :proxy_url, :logout_url, :service_url
|
7
|
+
attr_accessor :proxy_callback_url, :proxy_retrieval_url
|
8
|
+
|
9
|
+
def initialize(conf = nil)
|
10
|
+
configure(conf) if conf
|
11
|
+
end
|
12
|
+
|
13
|
+
def configure(conf)
|
14
|
+
#TODO: raise error if conf contains unrecognized cas options (this would help detect user typos in the config)
|
15
|
+
|
16
|
+
raise ArgumentError, "Missing :cas_base_url parameter!" unless conf[:cas_base_url]
|
17
|
+
|
18
|
+
@cas_base_url = conf[:cas_base_url].gsub(/\/$/, '')
|
19
|
+
|
20
|
+
@login_url = conf[:login_url]
|
21
|
+
@logout_url = conf[:logout_url]
|
22
|
+
@validate_url = conf[:validate_url]
|
23
|
+
@proxy_url = conf[:proxy_url]
|
24
|
+
@service_url = conf[:service_url]
|
25
|
+
@force_ssl_verification = conf[:force_ssl_verification]
|
26
|
+
@proxy_callback_url = conf[:proxy_callback_url]
|
27
|
+
@proxy_retrieval_url = conf[:proxy_retrieval_url]
|
28
|
+
|
29
|
+
@username_session_key = conf[:username_session_key] || :cas_user
|
30
|
+
@extra_attributes_session_key = conf[:extra_attributes_session_key] || :cas_extra_attributes
|
31
|
+
|
32
|
+
@log = CASClient::LoggerWrapper.new
|
33
|
+
@log.set_real_logger(conf[:logger]) if conf[:logger]
|
34
|
+
end
|
35
|
+
|
36
|
+
def login_url
|
37
|
+
@login_url || (cas_base_url + "/login")
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_url
|
41
|
+
@validate_url || (cas_base_url + "/proxyValidate")
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the CAS server's logout url.
|
45
|
+
#
|
46
|
+
# If a logout_url has not been explicitly configured,
|
47
|
+
# the default is cas_base_url + "/logout".
|
48
|
+
#
|
49
|
+
# destination_url:: Set this if you want the user to be
|
50
|
+
# able to immediately log back in. Generally
|
51
|
+
# you'll want to use something like <tt>request.referer</tt>.
|
52
|
+
# Note that the above behaviour describes RubyCAS-Server
|
53
|
+
# -- other CAS server implementations might use this
|
54
|
+
# parameter differently (or not at all).
|
55
|
+
# follow_url:: This satisfies section 2.3.1 of the CAS protocol spec.
|
56
|
+
# See http://www.ja-sig.org/products/cas/overview/protocol
|
57
|
+
def logout_url(destination_url = nil, follow_url = nil)
|
58
|
+
url = @logout_url || (cas_base_url + "/logout")
|
59
|
+
|
60
|
+
if destination_url
|
61
|
+
# if present, remove the 'ticket' parameter from the destination_url
|
62
|
+
duri = URI.parse(destination_url)
|
63
|
+
h = duri.query ? query_to_hash(duri.query) : {}
|
64
|
+
h.delete('ticket')
|
65
|
+
duri.query = hash_to_query(h)
|
66
|
+
destination_url = duri.to_s.gsub(/\?$/, '')
|
67
|
+
end
|
68
|
+
|
69
|
+
if destination_url || follow_url
|
70
|
+
uri = URI.parse(url)
|
71
|
+
h = uri.query ? query_to_hash(uri.query) : {}
|
72
|
+
h['destination'] = destination_url if destination_url
|
73
|
+
h['url'] = follow_url if follow_url
|
74
|
+
uri.query = hash_to_query(h)
|
75
|
+
uri.to_s
|
76
|
+
else
|
77
|
+
url
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def proxy_url
|
82
|
+
@proxy_url || (cas_base_url + "/proxy")
|
83
|
+
end
|
84
|
+
|
85
|
+
def validate_service_ticket(st)
|
86
|
+
uri = URI.parse(validate_url)
|
87
|
+
h = uri.query ? query_to_hash(uri.query) : {}
|
88
|
+
h['service'] = st.service
|
89
|
+
h['ticket'] = st.ticket
|
90
|
+
h['renew'] = 1 if st.renew
|
91
|
+
h['pgtUrl'] = proxy_callback_url if proxy_callback_url
|
92
|
+
uri.query = hash_to_query(h)
|
93
|
+
|
94
|
+
st.response = request_cas_response(uri, ValidationResponse)
|
95
|
+
|
96
|
+
return st
|
97
|
+
end
|
98
|
+
alias validate_proxy_ticket validate_service_ticket
|
99
|
+
|
100
|
+
# Returns true if the configured CAS server is up and responding;
|
101
|
+
# false otherwise.
|
102
|
+
def cas_server_is_up?
|
103
|
+
uri = URI.parse(login_url)
|
104
|
+
|
105
|
+
log.debug "Checking if CAS server at URI '#{uri}' is up..."
|
106
|
+
|
107
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
108
|
+
https.use_ssl = (uri.scheme == 'https')
|
109
|
+
https.verify_mode = (@force_ssl_verification ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE)
|
110
|
+
|
111
|
+
begin
|
112
|
+
raw_res = https.start do |conn|
|
113
|
+
conn.get("#{uri.path}?#{uri.query}")
|
114
|
+
end
|
115
|
+
rescue Errno::ECONNREFUSED => e
|
116
|
+
log.warn "CAS server did not respond! (#{e.inspect})"
|
117
|
+
return false
|
118
|
+
end
|
119
|
+
|
120
|
+
log.debug "CAS server responded with #{raw_res.inspect}:\n#{raw_res.body}"
|
121
|
+
|
122
|
+
return raw_res.kind_of?(Net::HTTPSuccess)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Requests a login using the given credentials for the given service;
|
126
|
+
# returns a LoginResponse object.
|
127
|
+
def login_to_service(credentials, service)
|
128
|
+
lt = request_login_ticket
|
129
|
+
|
130
|
+
data = credentials.merge(
|
131
|
+
:lt => lt,
|
132
|
+
:service => service
|
133
|
+
)
|
134
|
+
|
135
|
+
res = submit_data_to_cas(login_url, data)
|
136
|
+
response = CASClient::LoginResponse.new(res)
|
137
|
+
|
138
|
+
if response.is_success?
|
139
|
+
log.info("Login was successful for ticket: #{response.ticket.inspect}.")
|
140
|
+
end
|
141
|
+
|
142
|
+
return response
|
143
|
+
end
|
144
|
+
|
145
|
+
# Requests a login ticket from the CAS server for use in a login request;
|
146
|
+
# returns a LoginTicket object.
|
147
|
+
#
|
148
|
+
# This only works with RubyCAS-Server, since obtaining login
|
149
|
+
# tickets in this manner is not part of the official CAS spec.
|
150
|
+
def request_login_ticket
|
151
|
+
uri = URI.parse(login_url+'Ticket')
|
152
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
153
|
+
https.use_ssl = (uri.scheme == 'https')
|
154
|
+
https.verify_mode = (@force_ssl_verification ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE)
|
155
|
+
res = https.post(uri.path, ';')
|
156
|
+
|
157
|
+
raise CASException, res.body unless res.kind_of? Net::HTTPSuccess
|
158
|
+
|
159
|
+
res.body.strip
|
160
|
+
end
|
161
|
+
|
162
|
+
# Requests a proxy ticket from the CAS server for the given service
|
163
|
+
# using the given pgt (proxy granting ticket); returns a ProxyTicket
|
164
|
+
# object.
|
165
|
+
#
|
166
|
+
# The pgt required to request a proxy ticket is obtained as part of
|
167
|
+
# a ValidationResponse.
|
168
|
+
def request_proxy_ticket(pgt, target_service)
|
169
|
+
uri = URI.parse(proxy_url)
|
170
|
+
h = uri.query ? query_to_hash(uri.query) : {}
|
171
|
+
h['pgt'] = pgt.ticket
|
172
|
+
h['targetService'] = target_service
|
173
|
+
uri.query = hash_to_query(h)
|
174
|
+
|
175
|
+
pr = request_cas_response(uri, ProxyResponse)
|
176
|
+
|
177
|
+
pt = ProxyTicket.new(pr.proxy_ticket, target_service)
|
178
|
+
pt.response = pr
|
179
|
+
|
180
|
+
return pt
|
181
|
+
end
|
182
|
+
|
183
|
+
def retrieve_proxy_granting_ticket(pgt_iou)
|
184
|
+
uri = URI.parse(proxy_retrieval_url)
|
185
|
+
uri.query = (uri.query ? uri.query + "&" : "") + "pgtIou=#{CGI.escape(pgt_iou)}"
|
186
|
+
retrieve_url = uri.to_s
|
187
|
+
|
188
|
+
log.debug "Retrieving PGT for PGT IOU #{pgt_iou.inspect} from #{retrieve_url.inspect}"
|
189
|
+
|
190
|
+
# https = Net::HTTP.new(uri.host, uri.port)
|
191
|
+
# https.use_ssl = (uri.scheme == 'https')
|
192
|
+
# res = https.post(uri.path, ';')
|
193
|
+
uri = URI.parse(uri) unless uri.kind_of? URI
|
194
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
195
|
+
https.use_ssl = (uri.scheme == 'https')
|
196
|
+
https.verify_mode = (@force_ssl_verification ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE)
|
197
|
+
|
198
|
+
res = https.start do |conn|
|
199
|
+
conn.get("#{uri.path}?#{uri.query}")
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
raise CASException, res.body unless res.kind_of? Net::HTTPSuccess
|
204
|
+
|
205
|
+
ProxyGrantingTicket.new(res.body.strip, pgt_iou)
|
206
|
+
end
|
207
|
+
|
208
|
+
def add_service_to_login_url(service_url)
|
209
|
+
uri = URI.parse(login_url)
|
210
|
+
uri.query = (uri.query ? uri.query + "&" : "") + "service=#{CGI.escape(service_url)}"
|
211
|
+
uri.to_s
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
# Fetches a CAS response of the given type from the given URI.
|
216
|
+
# Type should be either ValidationResponse or ProxyResponse.
|
217
|
+
def request_cas_response(uri, type)
|
218
|
+
log.debug "Requesting CAS response for URI #{uri}"
|
219
|
+
|
220
|
+
uri = URI.parse(uri) unless uri.kind_of? URI
|
221
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
222
|
+
https.use_ssl = (uri.scheme == 'https')
|
223
|
+
https.verify_mode = (@force_ssl_verification ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE)
|
224
|
+
|
225
|
+
begin
|
226
|
+
raw_res = https.start do |conn|
|
227
|
+
conn.get("#{uri.path}?#{uri.query}")
|
228
|
+
end
|
229
|
+
rescue Errno::ECONNREFUSED => e
|
230
|
+
log.error "CAS server did not respond! (#{e.inspect})"
|
231
|
+
raise "The CAS authentication server at #{uri} is not responding!"
|
232
|
+
end
|
233
|
+
|
234
|
+
# We accept responses of type 422 since RubyCAS-Server generates these
|
235
|
+
# in response to requests from the client that are processable but contain
|
236
|
+
# invalid CAS data (for example an invalid service ticket).
|
237
|
+
if raw_res.kind_of?(Net::HTTPSuccess) || raw_res.code.to_i == 422
|
238
|
+
log.debug "CAS server responded with #{raw_res.inspect}:\n#{raw_res.body}"
|
239
|
+
else
|
240
|
+
log.error "CAS server responded with an error! (#{raw_res.inspect})"
|
241
|
+
raise "The CAS authentication server at #{uri} responded with an error (#{raw_res.inspect})!"
|
242
|
+
end
|
243
|
+
|
244
|
+
type.new(raw_res.body)
|
245
|
+
end
|
246
|
+
|
247
|
+
# Submits some data to the given URI and returns a Net::HTTPResponse.
|
248
|
+
def submit_data_to_cas(uri, data)
|
249
|
+
uri = URI.parse(uri) unless uri.kind_of? URI
|
250
|
+
req = Net::HTTP::Post.new(uri.path)
|
251
|
+
req.set_form_data(data, ';')
|
252
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
253
|
+
https.use_ssl = (uri.scheme == 'https')
|
254
|
+
https.verify_mode = (@force_ssl_verification ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE)
|
255
|
+
https.start {|conn| conn.request(req) }
|
256
|
+
end
|
257
|
+
|
258
|
+
def query_to_hash(query)
|
259
|
+
CGI.parse(query)
|
260
|
+
end
|
261
|
+
|
262
|
+
def hash_to_query(hash)
|
263
|
+
pairs = []
|
264
|
+
hash.each do |k, vals|
|
265
|
+
vals = [vals] unless vals.kind_of? Array
|
266
|
+
vals.each {|v| pairs << (v.nil? ? CGI.escape(k) : "#{CGI.escape(k)}=#{CGI.escape(v)}")}
|
267
|
+
end
|
268
|
+
pairs.join("&")
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module CASClient
|
2
|
+
module Frameworks
|
3
|
+
module Merb
|
4
|
+
module Filter
|
5
|
+
attr_reader :client
|
6
|
+
|
7
|
+
def cas_filter
|
8
|
+
@client ||= CASClient::Client.new(config)
|
9
|
+
|
10
|
+
service_ticket = read_ticket(self)
|
11
|
+
|
12
|
+
cas_login_url = client.add_service_to_login_url(read_service_url(self))
|
13
|
+
|
14
|
+
last_service_ticket = session[:cas_last_valid_ticket]
|
15
|
+
if (service_ticket && last_service_ticket &&
|
16
|
+
last_service_ticket.ticket == service_ticket.ticket &&
|
17
|
+
last_service_ticket.service == service_ticket.service)
|
18
|
+
|
19
|
+
# warn() rather than info() because we really shouldn't be re-validating the same ticket.
|
20
|
+
# The only time when this is acceptable is if the user manually does a refresh and the ticket
|
21
|
+
# happens to be in the URL.
|
22
|
+
log.warn("Reusing previously validated ticket since the new ticket and service are the same.")
|
23
|
+
service_ticket = last_service_ticket
|
24
|
+
elsif last_service_ticket &&
|
25
|
+
!config[:authenticate_on_every_request] &&
|
26
|
+
session[client.username_session_key]
|
27
|
+
# Re-use the previous ticket if the user already has a local CAS session (i.e. if they were already
|
28
|
+
# previously authenticated for this service). This is to prevent redirection to the CAS server on every
|
29
|
+
# request.
|
30
|
+
# This behaviour can be disabled (so that every request is routed through the CAS server) by setting
|
31
|
+
# the :authenticate_on_every_request config option to false.
|
32
|
+
log.debug "Existing local CAS session detected for #{session[client.username_session_key].inspect}. "+
|
33
|
+
"Previous ticket #{last_service_ticket.ticket.inspect} will be re-used."
|
34
|
+
service_ticket = last_service_ticket
|
35
|
+
end
|
36
|
+
|
37
|
+
if service_ticket
|
38
|
+
client.validate_service_ticket(service_ticket) unless service_ticket.has_been_validated?
|
39
|
+
validation_response = service_ticket.response
|
40
|
+
|
41
|
+
if service_ticket.is_valid?
|
42
|
+
log.info("Ticket #{service_ticket.inspect} for service #{service_ticket.service.inspect} " +
|
43
|
+
"belonging to user #{validation_response.user.inspect} is VALID.")
|
44
|
+
|
45
|
+
session[client.username_session_key] = validation_response.user
|
46
|
+
session[client.extra_attributes_session_key] = validation_response.extra_attributes
|
47
|
+
|
48
|
+
# Store the ticket in the session to avoid re-validating the same service
|
49
|
+
# ticket with the CAS server.
|
50
|
+
session[:cas_last_valid_ticket] = service_ticket
|
51
|
+
return true
|
52
|
+
else
|
53
|
+
log.warn("Ticket #{service_ticket.ticket.inspect} failed validation -- " +
|
54
|
+
"#{validation_response.failure_code}: #{validation_response.failure_message}")
|
55
|
+
redirect cas_login_url
|
56
|
+
throw :halt
|
57
|
+
end
|
58
|
+
else
|
59
|
+
log.warn("No ticket -- redirecting to #{cas_login_url}")
|
60
|
+
redirect cas_login_url
|
61
|
+
throw :halt
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
# Copied from Rails adapter
|
67
|
+
def read_ticket(controller)
|
68
|
+
ticket = controller.params[:ticket]
|
69
|
+
|
70
|
+
return nil unless ticket
|
71
|
+
|
72
|
+
log.debug("Request contains ticket #{ticket.inspect}.")
|
73
|
+
|
74
|
+
if ticket =~ /^PT-/
|
75
|
+
ProxyTicket.new(ticket, read_service_url(controller), controller.params[:renew])
|
76
|
+
else
|
77
|
+
ServiceTicket.new(ticket, read_service_url(controller), controller.params[:renew])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Also copied from Rails adapter
|
82
|
+
def read_service_url(controller)
|
83
|
+
if config[:service_url]
|
84
|
+
log.debug("Using explicitly set service url: #{config[:service_url]}")
|
85
|
+
return config[:service_url]
|
86
|
+
end
|
87
|
+
|
88
|
+
params = controller.params.dup
|
89
|
+
params.delete(:ticket)
|
90
|
+
service_url = request.protocol + '://' + request.host / controller.url(params.to_hash.symbolize_keys!)
|
91
|
+
log.debug("Guessed service url: #{service_url.inspect}")
|
92
|
+
return service_url
|
93
|
+
end
|
94
|
+
|
95
|
+
def log
|
96
|
+
::Merb.logger
|
97
|
+
end
|
98
|
+
|
99
|
+
def config
|
100
|
+
::Merb::Plugins.config[:"rubycas-client"]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|