rubycas-server 0.4.2 → 0.5.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/CHANGELOG.txt +37 -0
- data/Manifest.txt +10 -0
- data/Rakefile +3 -2
- data/bin/rubycas-server-ctl +1 -1
- data/config.example.yml +44 -11
- data/custom_views.example.rb +11 -0
- data/lib/casserver/authenticators/ldap.rb +11 -5
- data/lib/casserver/conf.rb +35 -12
- data/lib/casserver/controllers.rb +111 -23
- data/lib/casserver/models.rb +23 -0
- data/lib/casserver/postambles.rb +21 -24
- data/lib/casserver/utils.rb +16 -0
- data/lib/casserver/version.rb +3 -3
- data/lib/casserver/views.rb +50 -36
- data/lib/casserver.rb +9 -2
- data/lib/themes/cas.css +1 -0
- data/vendor/camping-1.5.180/lib/camping/db.rb +78 -0
- data/vendor/camping-1.5.180/lib/camping/fastcgi.rb +244 -0
- data/vendor/camping-1.5.180/lib/camping/reloader.rb +163 -0
- data/vendor/camping-1.5.180/lib/camping/session.rb +123 -0
- data/vendor/camping-1.5.180/lib/camping/webrick.rb +65 -0
- data/vendor/camping-1.5.180/lib/camping-unabridged.rb +762 -0
- data/vendor/camping-1.5.180/lib/camping.rb +55 -0
- metadata +10 -11
data/CHANGELOG.txt
CHANGED
@@ -1,3 +1,40 @@
|
|
1
|
+
=== 0.5.0 :: 2007-09-20
|
2
|
+
|
3
|
+
* Gateway requests should now be handled correctly. When the request to the
|
4
|
+
login page is made with gateway=true as one of the parameters, the CAS
|
5
|
+
server will immediately redirect back to the target service along with
|
6
|
+
a service ticket if an SSO session exists for the user (or without a
|
7
|
+
service ticket if there is no pre-existing SSO session).
|
8
|
+
Note that if you are using RubyCAS-Client and want gatewaying, you will
|
9
|
+
need to upgrade it to 1.1.0 as gatewaying was broken in prior versions.
|
10
|
+
* If gateway=true is specified as part of the logout URI, the server will
|
11
|
+
log the user out and immediately redirect them back to the specified
|
12
|
+
service. In other words, you can now do "gatewayed logouts" as well
|
13
|
+
as logins.
|
14
|
+
* A login ticket can now be remotely requested from the server by placing
|
15
|
+
a POST request to '/loginTicket'.
|
16
|
+
* The login view can now be made to return only the login form. This is
|
17
|
+
done by adding the 'onlyLoginForm' parameter to the '/login' request.
|
18
|
+
Optionally, a 'submitToURI' parameter can be supplied to force the login
|
19
|
+
form to submit to the given URI (otherwise the server will try to figure
|
20
|
+
out the full URI to its own login controller). This functionality may be
|
21
|
+
useful when you want to embed the login form in some external page, as
|
22
|
+
an IFRAME otherwise.
|
23
|
+
* Custom views can now be used to override the default Markaby templates
|
24
|
+
by specifying a 'custom_views_file' option in the configuration. See
|
25
|
+
custom_views.example.rb. [jzylks]
|
26
|
+
* Table names have been shortened to work with Oracle. A migration has
|
27
|
+
been added that should do the shortening for you the first time you run
|
28
|
+
this new RubyCAS-Server version.
|
29
|
+
* Multiple authenticators can now be specified. During authentication,
|
30
|
+
credentials are presented to the first authenticator, then the second,
|
31
|
+
and so on, until the user is validated by any one authenticator or fails
|
32
|
+
validation for all of them. [jzylks]
|
33
|
+
* When using webrick, you can now run with SSL disabled by omitting the
|
34
|
+
ssl_cert and ssl_key parameters.
|
35
|
+
* Changed incorrect MySQL example database configuration -- option should
|
36
|
+
be 'host:' not 'server:' (issue #22).
|
37
|
+
|
1
38
|
=== 0.4.2 :: 2007-07-26
|
2
39
|
|
3
40
|
* The LDAP/AD authenticator has been largely re-written. The code is a bit
|
data/Manifest.txt
CHANGED
@@ -6,6 +6,7 @@ Rakefile
|
|
6
6
|
bin/rubycas-server
|
7
7
|
bin/rubycas-server-ctl
|
8
8
|
config.example.yml
|
9
|
+
custom_views.example.rb
|
9
10
|
lib/casserver.rb
|
10
11
|
lib/casserver/authenticators/active_directory_ldap.rb
|
11
12
|
lib/casserver/authenticators/base.rb
|
@@ -35,3 +36,12 @@ lib/themes/warning.png
|
|
35
36
|
resources/init.d.sh
|
36
37
|
setup.rb
|
37
38
|
test/test_casserver.rb
|
39
|
+
|
40
|
+
vendor/camping-1.5.180/lib/camping-unabridged.rb
|
41
|
+
vendor/camping-1.5.180/lib/camping.rb
|
42
|
+
vendor/camping-1.5.180/lib/camping/db.rb
|
43
|
+
vendor/camping-1.5.180/lib/camping/fastcgi.rb
|
44
|
+
vendor/camping-1.5.180/lib/camping/reloader.rb
|
45
|
+
vendor/camping-1.5.180/lib/camping/session.rb
|
46
|
+
vendor/camping-1.5.180/lib/camping/webrick.rb
|
47
|
+
|
data/Rakefile
CHANGED
@@ -19,14 +19,15 @@ RUBYFORGE_PROJECT = "rubycas-server" # The unix name for your project
|
|
19
19
|
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
20
20
|
|
21
21
|
DEPS = [
|
22
|
-
['camping', '>= 1.5'],
|
22
|
+
# ['camping', '>= 1.5'], # camping is now bundled with rubycas-server
|
23
23
|
['activesupport', '>= 1.4.0'],
|
24
24
|
['activerecord', '>=1.15.3']
|
25
25
|
]
|
26
26
|
|
27
27
|
|
28
28
|
NAME = "rubycas-server"
|
29
|
-
REV = nil
|
29
|
+
REV = nil
|
30
|
+
#REV = `svn info`[/Revision: (\d+)/, 1] rescue nil
|
30
31
|
VERS = ENV['VERSION'] || (CASServer::VERSION::STRING + (REV ? ".#{REV}" : ""))
|
31
32
|
CLEAN.include ['**/.*.sw?', '*.gem', '.config']
|
32
33
|
RDOC_OPTS = ['--quiet', '--title', "RubyCAS-Server #{VERS} Documentation",
|
data/bin/rubycas-server-ctl
CHANGED
@@ -21,7 +21,7 @@ def start
|
|
21
21
|
when :ok
|
22
22
|
$stderr.puts "rubycas-server is already running"
|
23
23
|
exit 1
|
24
|
-
when :not_running
|
24
|
+
when :not_running, :empty_pid
|
25
25
|
$stderr.puts "The pid file '#{@options[:pid_file]}' exists but rubycas-server is not running." +
|
26
26
|
" The pid file will be automatically deleted for you, but this shouldn't have happened!"
|
27
27
|
File.delete(@options[:pid_file])
|
data/config.example.yml
CHANGED
@@ -49,22 +49,25 @@ ssl_cert: /path/to/your/ssl.pem
|
|
49
49
|
#
|
50
50
|
# By default, we use MySQL, since it is widely used and does not require any additional
|
51
51
|
# ruby libraries besides ActiveRecord.
|
52
|
-
#
|
53
|
-
# Instead of MySQL you can use SQLite3, PostgreSQL, MSSQL, or anything else supported
|
54
|
-
# by ActiveRecord.
|
55
52
|
#
|
56
|
-
#
|
53
|
+
# With MySQL, your config would be something like the following:
|
54
|
+
# (be sure to create the casserver database in MySQL beforehand,
|
55
|
+
# i.e. `mysqladmin -u root create casserver`)
|
57
56
|
|
58
57
|
database:
|
59
58
|
adapter: mysql
|
60
59
|
database: casserver
|
61
60
|
username: root
|
62
61
|
password:
|
63
|
-
|
62
|
+
host: localhost
|
64
63
|
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
64
|
+
#
|
65
|
+
# Instead of MySQL you can use SQLite3, PostgreSQL, MSSQL, or anything else supported
|
66
|
+
# by ActiveRecord.
|
67
|
+
#
|
68
|
+
# With SQLite3 (which does not require a separate database server), your configuration
|
69
|
+
# would look something like the following (don't forget to install the
|
70
|
+
# sqlite3-ruby gem beforehand!):
|
68
71
|
#
|
69
72
|
#database:
|
70
73
|
# adapter: sqlite3
|
@@ -95,7 +98,7 @@ database:
|
|
95
98
|
# database:
|
96
99
|
# adapter: mysql
|
97
100
|
# database: some_database_with_users_table
|
98
|
-
#
|
101
|
+
# username: root
|
99
102
|
# password:
|
100
103
|
# server: localhost
|
101
104
|
# user_table: user
|
@@ -128,7 +131,7 @@ database:
|
|
128
131
|
#
|
129
132
|
# It is possible to authenticate against Active Directory without the
|
130
133
|
# authenticator user, but this requires that users type in their CN as
|
131
|
-
# the username
|
134
|
+
# the username rather than typing in their sAMAccountName. In other words
|
132
135
|
# users will likely have to authenticate by typing their full name,
|
133
136
|
# rather than their username. If you prefer to do this, then just
|
134
137
|
# omit the auth_user and auth_password values in the above example.
|
@@ -170,7 +173,35 @@ database:
|
|
170
173
|
# source: /path/to/source.rb
|
171
174
|
# option_a: foo
|
172
175
|
# another_option: yeeha
|
173
|
-
|
176
|
+
#
|
177
|
+
# ==> Multiple Authenticators
|
178
|
+
# If you need to have more than one source for authentication, such as an LDAP directory
|
179
|
+
# and a database, you can use multiple authenticators by making :authenticator an array
|
180
|
+
# of authenticators.
|
181
|
+
#
|
182
|
+
#authenticator:
|
183
|
+
# -
|
184
|
+
# class: CASServer::Authenticators::ActiveDirectoryLDAP
|
185
|
+
# ldap:
|
186
|
+
# server: ad.example.net
|
187
|
+
# port: 389
|
188
|
+
# base: dc=example,dc=net
|
189
|
+
# filter: (objectClass=person)
|
190
|
+
# -
|
191
|
+
# class: CASServer::Authenticators::SQL
|
192
|
+
# database:
|
193
|
+
# adapter: mysql
|
194
|
+
# database: some_database_with_users_table
|
195
|
+
# user: root
|
196
|
+
# password:
|
197
|
+
# server: localhost
|
198
|
+
# user_table: user
|
199
|
+
# username_column: username
|
200
|
+
# password_column: password
|
201
|
+
#
|
202
|
+
# During authentication, the user credentials will be checked against the first
|
203
|
+
# authenticator and on failure fall through to the second authenticator.
|
204
|
+
#
|
174
205
|
|
175
206
|
##### LOOK & FEEL ######################################################################
|
176
207
|
|
@@ -192,6 +223,8 @@ organization: CAS
|
|
192
223
|
# A short bit of text that shows up on the login page. You can make this blank if you prefer.
|
193
224
|
infoline: Powered by <a href="http://code.google.com/p/rubycas-server/">RubyCAS-Server</a>
|
194
225
|
|
226
|
+
# Custom views file. Overrides methodes in lib/casserver/views.rb
|
227
|
+
#custom_views_file: /path/to/custom/views.rb
|
195
228
|
|
196
229
|
##### LOGGING #########################################################################
|
197
230
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Custom views file; add methods to the module definition below
|
2
|
+
|
3
|
+
module CASServer::Views
|
4
|
+
|
5
|
+
# Override views here, for example, a custom login form:
|
6
|
+
def login_form
|
7
|
+
# Add your custom login form here, using Markaby
|
8
|
+
# See the original views.rb file at lib/casserver/views.rb for method names and usage
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
@@ -11,9 +11,9 @@ end
|
|
11
11
|
class CASServer::Authenticators::LDAP < CASServer::Authenticators::Base
|
12
12
|
def validate(credentials)
|
13
13
|
read_standard_credentials(credentials)
|
14
|
-
|
14
|
+
|
15
15
|
return false if @password.blank?
|
16
|
-
|
16
|
+
|
17
17
|
raise CASServer::AuthenticatorError, "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
|
18
18
|
raise CASServer::AuthenticatorError, "Invalid authenticator configuration!" unless @options[:ldap]
|
19
19
|
raise CASServer::AuthenticatorError, "You must specify an ldap server in the configuration!" unless @options[:ldap][:server]
|
@@ -68,8 +68,14 @@ class CASServer::Authenticators::LDAP < CASServer::Authenticators::Base
|
|
68
68
|
|
69
69
|
username_attribute = options[:ldap][:username_attribute] || default_username_attribute
|
70
70
|
|
71
|
-
filter = Net::LDAP::Filter.construct(@options[:ldap][:filter])
|
72
|
-
|
71
|
+
filter = Net::LDAP::Filter.construct(@options[:ldap][:filter]) if
|
72
|
+
@options[:ldap][:filter] && !@options[:ldap][:filter].blank?
|
73
|
+
username_filter = Net::LDAP::Filter.eq(username_attribute, @username)
|
74
|
+
if filter
|
75
|
+
filter &= username_filter
|
76
|
+
else
|
77
|
+
filter = username_filter
|
78
|
+
end
|
73
79
|
|
74
80
|
@ldap.bind_as(:base => @options[:ldap][:base], :password => @password, :filter => filter)
|
75
81
|
end
|
@@ -86,4 +92,4 @@ class CASServer::Authenticators::LDAP < CASServer::Authenticators::Base
|
|
86
92
|
@ldap.authenticate(cn, @password)
|
87
93
|
@ldap.bind
|
88
94
|
end
|
89
|
-
end
|
95
|
+
end
|
data/lib/casserver/conf.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# load configuration
|
2
|
+
|
2
3
|
begin
|
3
4
|
if $CONFIG_FILE
|
4
5
|
conf_file = $CONFIG_FILE
|
@@ -33,8 +34,7 @@ begin
|
|
33
34
|
" suit your needs and then run rubycas-server again.\n"
|
34
35
|
exit 1
|
35
36
|
end
|
36
|
-
|
37
|
-
|
37
|
+
|
38
38
|
loaded_conf = HashWithIndifferentAccess.new(YAML.load_file(conf_file))
|
39
39
|
|
40
40
|
if $CONF
|
@@ -42,21 +42,44 @@ begin
|
|
42
42
|
else
|
43
43
|
$CONF = loaded_conf
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
|
+
if $CONF[:authenticator].instance_of? Array
|
47
|
+
$CONF[:authenticator].each_index { |auth_index| $CONF[:authenticator][auth_index] = HashWithIndifferentAccess.new($CONF[:authenticator][auth_index])}
|
48
|
+
end
|
49
|
+
|
50
|
+
$AUTH = []
|
46
51
|
begin
|
47
52
|
# attempt to instantiate the authenticator
|
48
|
-
|
49
|
-
|
50
|
-
if !$CONF[:authenticator][:source].nil?
|
51
|
-
# config.yml explicitly names source file
|
52
|
-
require $CONF[:authenticator][:source]
|
53
|
+
if $CONF[:authenticator].instance_of? Array
|
54
|
+
$CONF[:authenticator].each { |authenticator| $AUTH << authenticator[:class].constantize.new}
|
53
55
|
else
|
54
|
-
|
55
|
-
auth_rb = $CONF[:authenticator][:class].underscore.gsub('cas_server/', '')
|
56
|
-
require 'casserver/'+auth_rb
|
56
|
+
$AUTH << $CONF[:authenticator][:class].constantize.new
|
57
57
|
end
|
58
|
+
rescue NameError
|
59
|
+
if $CONF[:authenticator].instance_of? Array
|
60
|
+
$CONF[:authenticator].each do |authenticator|
|
61
|
+
if !authenticator[:source].nil?
|
62
|
+
# config.yml explicitly names source file
|
63
|
+
require authenticator[:source]
|
64
|
+
else
|
65
|
+
# the authenticator class hasn't yet been loaded, so lets try to load it from the casserver/authenticators directory
|
66
|
+
auth_rb = authenticator[:class].underscore.gsub('cas_server/', '')
|
67
|
+
require 'casserver/'+auth_rb
|
68
|
+
end
|
69
|
+
$AUTH << authenticator[:class].constantize.new
|
70
|
+
end
|
71
|
+
else
|
72
|
+
if !$CONF[:authenticator][:source].nil?
|
73
|
+
# config.yml explicitly names source file
|
74
|
+
require $CONF[:authenticator][:source]
|
75
|
+
else
|
76
|
+
# the authenticator class hasn't yet been loaded, so lets try to load it from the casserver/authenticators directory
|
77
|
+
auth_rb = $CONF[:authenticator][:class].underscore.gsub('cas_server/', '')
|
78
|
+
require 'casserver/'+auth_rb
|
79
|
+
end
|
58
80
|
|
59
|
-
|
81
|
+
$AUTH << $CONF[:authenticator][:class].constantize.new
|
82
|
+
end
|
60
83
|
end
|
61
84
|
rescue
|
62
85
|
raise "Your RubyCAS-Server configuration may be invalid."+
|
@@ -9,6 +9,8 @@ module CASServer::Controllers
|
|
9
9
|
|
10
10
|
# 2.1.1
|
11
11
|
def get
|
12
|
+
CASServer::Utils::log_controller_action(self.class, @input)
|
13
|
+
|
12
14
|
# make sure there's no caching
|
13
15
|
headers['Pragma'] = 'no-cache'
|
14
16
|
headers['Cache-Control'] = 'no-store'
|
@@ -17,7 +19,7 @@ module CASServer::Controllers
|
|
17
19
|
# optional params
|
18
20
|
@service = @input['service']
|
19
21
|
@renew = @input['renew']
|
20
|
-
@gateway = @input['gateway']
|
22
|
+
@gateway = @input['gateway'] == 'true' || @input['gateway'] == '1'
|
21
23
|
|
22
24
|
if tgc = @cookies[:tgt]
|
23
25
|
tgt, tgt_error = validate_ticket_granting_ticket(tgc)
|
@@ -28,13 +30,21 @@ module CASServer::Controllers
|
|
28
30
|
end
|
29
31
|
|
30
32
|
begin
|
31
|
-
if @service
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
if @service
|
34
|
+
if !@renew && tgt && !tgt_error
|
35
|
+
st = generate_service_ticket(@service, tgt.username)
|
36
|
+
service_with_ticket = service_uri_with_ticket(@service, st)
|
37
|
+
$LOG.info("User '#{tgt.username}' authenticated based on ticket granting cookie. Redirecting to service '#{@service}'.")
|
38
|
+
return redirect(service_with_ticket, :status => 303) # response code 303 means "See Other" (see Appendix B in CAS Protocol spec)
|
39
|
+
elsif @gateway
|
40
|
+
$LOG.info("Redirecting unauthenticated gateway request to service '#{@service}'.")
|
41
|
+
return redirect(@service, :status => 303)
|
42
|
+
end
|
43
|
+
elsif @gateway
|
44
|
+
$LOG.error("This is a gateway request but no service parameter was given!")
|
45
|
+
@message = {:type => 'mistake', :message => "The server cannot fulfill this gateway request because no service parameter was given."}
|
36
46
|
end
|
37
|
-
rescue
|
47
|
+
rescue # FIXME: shouldn't this only rescue URI::InvalidURIError?
|
38
48
|
$LOG.error("The service '#{@service}' is not a valid URI!")
|
39
49
|
@message = {:type => 'mistake', :message => "The target service your browser supplied appears to be invalid. Please contact your system administrator for help."}
|
40
50
|
end
|
@@ -45,11 +55,37 @@ module CASServer::Controllers
|
|
45
55
|
|
46
56
|
@lt = lt.ticket
|
47
57
|
|
48
|
-
|
58
|
+
$LOG.debug(env)
|
59
|
+
|
60
|
+
# If the 'onlyLoginForm' parameter is specified, we will only return the
|
61
|
+
# login form part of the page. This is useful for when you want to
|
62
|
+
# embed the login form in some external page (as an IFRAME, or otherwise).
|
63
|
+
# The optional 'submitToURI' parameter can be given to explicitly set the
|
64
|
+
# action for the form, otherwise the server will try to guess this for you.
|
65
|
+
if @input.has_key? 'onlyLoginForm'
|
66
|
+
if env['HTTP_HOST']
|
67
|
+
guessed_login_uri = "http#{env['HTTPS'] && env['HTTPS'] == 'on' ? 's' : ''}://#{env['REQUEST_URI']}#{self / '/login'}"
|
68
|
+
else
|
69
|
+
guessed_login_uri = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
@form_action = @input['submitToURI'] || guessed_login_uri
|
73
|
+
|
74
|
+
if @form_action
|
75
|
+
render :login_form
|
76
|
+
else
|
77
|
+
@status = 500
|
78
|
+
"Could not guess the CAS login URI. Please supply a submitURI parameter with your request."
|
79
|
+
end
|
80
|
+
else
|
81
|
+
render :login
|
82
|
+
end
|
49
83
|
end
|
50
84
|
|
51
85
|
# 2.2
|
52
86
|
def post
|
87
|
+
CASServer::Utils::log_controller_action(self.class, @input)
|
88
|
+
|
53
89
|
# 2.2.1 (optional)
|
54
90
|
@service = @input['service']
|
55
91
|
@warn = @input['warn']
|
@@ -69,12 +105,20 @@ module CASServer::Controllers
|
|
69
105
|
# generate another login ticket to allow for re-submitting the form after a post
|
70
106
|
@lt = generate_login_ticket.ticket
|
71
107
|
|
72
|
-
$
|
73
|
-
|
108
|
+
if $CONF[:authenticator].instance_of? Array
|
109
|
+
$AUTH.each_index {|auth_index| $AUTH[auth_index].configure(CASServer::Conf.authenticator[auth_index])}
|
110
|
+
else
|
111
|
+
$AUTH[0].configure(CASServer::Conf.authenticator)
|
112
|
+
end
|
113
|
+
|
74
114
|
$LOG.debug("Logging in with username: #{@username}, lt: #{@lt}, service: #{@service}, auth: #{$AUTH}")
|
75
115
|
|
116
|
+
credentials_are_valid = false
|
76
117
|
begin
|
77
|
-
|
118
|
+
$AUTH.each do |auth|
|
119
|
+
credentials_are_valid = auth.validate(:username => @username, :password => @password, :service => @service)
|
120
|
+
break if credentials_are_valid
|
121
|
+
end
|
78
122
|
rescue CASServer::AuthenticatorError => e
|
79
123
|
$LOG.error(e)
|
80
124
|
@message = {:type => 'mistake', :message => e.to_s}
|
@@ -82,10 +126,10 @@ module CASServer::Controllers
|
|
82
126
|
end
|
83
127
|
|
84
128
|
if credentials_are_valid
|
85
|
-
$LOG.info("Credentials for username '#{
|
129
|
+
$LOG.info("Credentials for username '#{@username}' successfully validated")
|
86
130
|
|
87
131
|
# 3.6 (ticket-granting cookie)
|
88
|
-
tgt = generate_ticket_granting_ticket(
|
132
|
+
tgt = generate_ticket_granting_ticket(@username)
|
89
133
|
|
90
134
|
if CASServer::Conf.expire_sessions
|
91
135
|
expires = CASServer::Conf.ticket_granting_ticket_expiry.to_i.from_now
|
@@ -98,17 +142,17 @@ module CASServer::Controllers
|
|
98
142
|
# seem to be an easy way to set cookie expire times in Camping :(
|
99
143
|
@cookies[:tgt] = tgt.to_s
|
100
144
|
|
101
|
-
$LOG.debug("Ticket granting cookie '#{@cookies[:tgt]}' granted to '#{
|
145
|
+
$LOG.debug("Ticket granting cookie '#{@cookies[:tgt]}' granted to '#{@username}'. #{expiry_info}")
|
102
146
|
|
103
147
|
if @service.blank?
|
104
|
-
$LOG.info("Successfully authenticated user '#{
|
148
|
+
$LOG.info("Successfully authenticated user '#{@username}' at '#{tgt.client_hostname}'. No service param was given, so we will not redirect.")
|
105
149
|
@message = {:type => 'confirmation', :message => "You have successfully logged in."}
|
106
150
|
else
|
107
|
-
@st = generate_service_ticket(@service,
|
151
|
+
@st = generate_service_ticket(@service, @username)
|
108
152
|
begin
|
109
153
|
service_with_ticket = service_uri_with_ticket(@service, @st)
|
110
154
|
|
111
|
-
$LOG.info("Redirecting authenticated user '#{
|
155
|
+
$LOG.info("Redirecting authenticated user '#{@username}' at '#{@st.client_hostname}' to service '#{@service}'")
|
112
156
|
return redirect(service_with_ticket, :status => 303) # response code 303 means "See Other" (see Appendix B in CAS Protocol spec)
|
113
157
|
rescue URI::InvalidURIError
|
114
158
|
$LOG.error("The service '#{@service}' is not a valid URI!")
|
@@ -116,7 +160,7 @@ module CASServer::Controllers
|
|
116
160
|
end
|
117
161
|
end
|
118
162
|
else
|
119
|
-
$LOG.warn("Invalid credentials given for user '#{
|
163
|
+
$LOG.warn("Invalid credentials given for user '#{@username}'")
|
120
164
|
@message = {:type => 'mistake', :message => "Incorrect username or password."}
|
121
165
|
end
|
122
166
|
|
@@ -130,13 +174,17 @@ module CASServer::Controllers
|
|
130
174
|
|
131
175
|
# 2.3.1
|
132
176
|
def get
|
177
|
+
CASServer::Utils::log_controller_action(self.class, @input)
|
178
|
+
|
133
179
|
# The behaviour here is somewhat non-standard. Rather than showing just a blank
|
134
180
|
# "logout" page, we take the user back to the login page with a "you have been logged out"
|
135
|
-
# message, allowing for an opportunity to immediately log back in. This makes
|
136
|
-
#
|
181
|
+
# message, allowing for an opportunity to immediately log back in. This makes it
|
182
|
+
# easier for the user to log out and log in as someone else.
|
137
183
|
@service = @input['url'] || @input['service']
|
138
184
|
# TODO: display service name in view as per 2.3.2
|
139
185
|
|
186
|
+
@gateway = @input['gateway'] == 'true' || @input['gateway'] == '1'
|
187
|
+
|
140
188
|
tgt = CASServer::Models::TicketGrantingTicket.find_by_ticket(@cookies[:tgt])
|
141
189
|
|
142
190
|
@cookies.delete :tgt
|
@@ -162,7 +210,11 @@ module CASServer::Controllers
|
|
162
210
|
|
163
211
|
@lt = generate_login_ticket
|
164
212
|
|
165
|
-
|
213
|
+
if @gateway && @service
|
214
|
+
redirect(@service, :status => 303)
|
215
|
+
else
|
216
|
+
render :login
|
217
|
+
end
|
166
218
|
end
|
167
219
|
end
|
168
220
|
|
@@ -172,6 +224,8 @@ module CASServer::Controllers
|
|
172
224
|
|
173
225
|
# 2.4.1
|
174
226
|
def get
|
227
|
+
CASServer::Utils::log_controller_action(self.class, @input)
|
228
|
+
|
175
229
|
# required
|
176
230
|
@service = @input['service']
|
177
231
|
@ticket = @input['ticket']
|
@@ -193,6 +247,8 @@ module CASServer::Controllers
|
|
193
247
|
|
194
248
|
# 2.5.1
|
195
249
|
def get
|
250
|
+
CASServer::Utils::log_controller_action(self.class, @input)
|
251
|
+
|
196
252
|
# required
|
197
253
|
@service = @input['service']
|
198
254
|
@ticket = @input['ticket']
|
@@ -221,6 +277,8 @@ module CASServer::Controllers
|
|
221
277
|
|
222
278
|
# 2.6.1
|
223
279
|
def get
|
280
|
+
CASServer::Utils::log_controller_action(self.class, @input)
|
281
|
+
|
224
282
|
# required
|
225
283
|
@service = @input['service']
|
226
284
|
@ticket = @input['ticket']
|
@@ -259,6 +317,8 @@ module CASServer::Controllers
|
|
259
317
|
|
260
318
|
# 2.7
|
261
319
|
def get
|
320
|
+
CASServer::Utils::log_controller_action(self.class, @input)
|
321
|
+
|
262
322
|
# required
|
263
323
|
@ticket = @input['pgt']
|
264
324
|
@target_service = @input['targetService']
|
@@ -274,13 +334,41 @@ module CASServer::Controllers
|
|
274
334
|
end
|
275
335
|
end
|
276
336
|
|
337
|
+
# Controller for obtaining login tickets.
|
338
|
+
# This is useful when you want to build a custom login form located on a
|
339
|
+
# remote server. Your form will have to include a valid login ticket
|
340
|
+
# value, and this can be fetched from the CAS server using this controller'
|
341
|
+
# POST method.
|
342
|
+
class LoginTicketDispenser < R '/loginTicket'
|
343
|
+
include CASServer::CAS
|
344
|
+
|
345
|
+
def get
|
346
|
+
CASServer::Utils::log_controller_action(self.class, @input)
|
347
|
+
$LOG.error("Tried to use login ticket dispenser with get method!")
|
348
|
+
@status = 500
|
349
|
+
"To generate a login ticket, you must make a POST request."
|
350
|
+
end
|
351
|
+
|
352
|
+
# Renders a page with a login ticket (and only the login ticket)
|
353
|
+
# in the response body.
|
354
|
+
def post
|
355
|
+
CASServer::Utils::log_controller_action(self.class, @input)
|
356
|
+
lt = generate_login_ticket
|
357
|
+
|
358
|
+
$LOG.debug("Generated login ticket: #{lt}, host: #{env['REMOTE_HOST'] || env['REMOTE_ADDR']}")
|
359
|
+
|
360
|
+
@lt = lt.ticket
|
361
|
+
|
362
|
+
@lt
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
277
366
|
class Themes < R '/themes/(.+)'
|
278
367
|
MIME_TYPES = {'.css' => 'text/css', '.js' => 'text/javascript',
|
279
368
|
'.jpg' => 'image/jpeg'}
|
280
369
|
PATH = CASServer::Conf.themes_dir || File.expand_path(File.dirname(__FILE__))+'/../themes'
|
281
370
|
|
282
|
-
def get(path)
|
283
|
-
@headers['Content-Type'] = MIME_TYPES[path[/\.\w+$/, 0]] || "text/plain"
|
371
|
+
def get(path)@headers['Content-Type'] = MIME_TYPES[path[/\.\w+$/, 0]] || "text/plain"
|
284
372
|
unless path.include? ".." # prevent directory traversal attacks
|
285
373
|
@headers['X-Sendfile'] = "#{PATH}/#{path}"
|
286
374
|
else
|
data/lib/casserver/models.rb
CHANGED
@@ -31,10 +31,12 @@ module CASServer::Models
|
|
31
31
|
end
|
32
32
|
|
33
33
|
class LoginTicket < Ticket
|
34
|
+
set_table_name 'casserver_lt'
|
34
35
|
include Consumable
|
35
36
|
end
|
36
37
|
|
37
38
|
class ServiceTicket < Ticket
|
39
|
+
set_table_name 'casserver_st'
|
38
40
|
include Consumable
|
39
41
|
|
40
42
|
def matches_service?(service)
|
@@ -50,9 +52,11 @@ module CASServer::Models
|
|
50
52
|
end
|
51
53
|
|
52
54
|
class TicketGrantingTicket < Ticket
|
55
|
+
set_table_name 'casserver_tgt'
|
53
56
|
end
|
54
57
|
|
55
58
|
class ProxyGrantingTicket < Ticket
|
59
|
+
set_table_name 'casserver_pgt'
|
56
60
|
belongs_to :service_ticket
|
57
61
|
has_many :proxy_tickets, :dependent => :destroy
|
58
62
|
end
|
@@ -113,4 +117,23 @@ module CASServer::Models
|
|
113
117
|
drop_table :casserver_login_tickets
|
114
118
|
end
|
115
119
|
end
|
120
|
+
|
121
|
+
# Oracle table names cannot exceed 30 chars...
|
122
|
+
# See http://code.google.com/p/rubycas-server/issues/detail?id=15
|
123
|
+
class ShortenTableNames < V 0.5
|
124
|
+
def self.up
|
125
|
+
$LOG.info("Shortening table names")
|
126
|
+
rename_table :casserver_login_tickets, :casserver_lt
|
127
|
+
rename_table :casserver_service_tickets, :casserver_st
|
128
|
+
rename_table :casserver_ticket_granting_tickets, :casserver_tgt
|
129
|
+
rename_table :casserver_proxy_granting_tickets, :casserver_pgt
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.down
|
133
|
+
rename_table :casserver_lt, :cassserver_login_tickets
|
134
|
+
rename_table :casserver_st, :casserver_service_tickets
|
135
|
+
rename_table :casserver_tgt, :casserver_ticket_granting_tickets
|
136
|
+
rename_table :casserver_pgt, :casserver_proxy_granting_tickets
|
137
|
+
end
|
138
|
+
end
|
116
139
|
end
|