p8-casablanca 0.0.3.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,11 +1,17 @@
1
+ === 0.1.0 / 2009-02-18
2
+
3
+ * 1 major enhancement
4
+
5
+ * Implemented gatewaying for rails filter
6
+
1
7
  === 0.0.2 / 2009-01-07
2
8
 
3
9
  * 1 major enhancement
4
10
 
5
- * Implmented renew
11
+ * Implemented renew
6
12
  * Added logger
7
13
 
8
- === 0.0.2 / 2009-01-07
14
+ === 0.0.1 / 2009-01-07
9
15
 
10
16
  * 1 major enhancement
11
17
 
data/Manifest.txt CHANGED
@@ -2,18 +2,18 @@ History.txt
2
2
  Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
- init.rb
6
5
  bin/casablanca
6
+ init.rb
7
7
  lib/casablanca.rb
8
8
  lib/casablanca/cli.rb
9
9
  lib/casablanca/client.rb
10
- lib/casablanca/rails/filter.rb
11
10
  lib/casablanca/rails/cas_proxy_callback_controller.rb
11
+ lib/casablanca/rails/filter.rb
12
12
  lib/casablanca/response_parsers.rb
13
13
  test/mocks.rb
14
14
  test/test_client.rb
15
15
  test/test_helper.rb
16
16
  test/test_parser.rb
17
- test/test_rails_filter.rb
18
17
  test/test_rails_cas_proxy_callback_controller.rb
19
- test/test_ticket.rb
18
+ test/test_rails_filter.rb
19
+ test/test_ticket.rb
data/README.txt CHANGED
@@ -10,17 +10,16 @@ Casablanca is a ruby single sign-on client for the CAS 2.0 protocol.
10
10
 
11
11
  * Includes a commandline Client to test getting service tickets from a CAS server
12
12
  * It can be run as a Rails plugin.
13
- * Gatewaying (permitting the user to continue without authentication) is not implemented.
14
- Just skip the filter for those actions.
15
13
 
16
14
  == TODO:
17
15
 
18
- * Implement proxing
16
+ * Add extra attributes returned from the server
17
+ * Implement proxying
19
18
  * Check for single signout
20
19
 
21
20
  == SYNOPSIS:
22
21
 
23
- Commandline:
22
+ === Commandline:
24
23
 
25
24
  % casablanca
26
25
 
@@ -35,35 +34,39 @@ In IRB:
35
34
  C.authenticate_ticket(ticket)
36
35
 
37
36
 
38
- In a Rails project:
37
+ === Rails:
39
38
  - environment.rb:
40
39
 
41
- Casablanca::RailsFilter.config do |config|
40
+ Casablanca::Rails::Config.config do |config|
42
41
  config[:cas_server_url] = "http://localhost:4567"
43
- config[:service_url] = "http://localhost:3000"
44
42
  # Always require new credentials for authentication
45
43
  config[:renew] = true
46
44
  end
47
45
 
48
- - Add the following to application.rb:
49
46
 
50
- before_filter Casablanca::RailsFilter
47
+
48
+ before_filter Casablanca::Rails::Filter
49
+ # If you want users without credentials to view the page as well use the Gateway filter
50
+ # before_filter Casablanca::Rails::GatewayFilter
51
+
52
+
53
+ - Add something like the following to application.rb to get the current user from the Cas session:
51
54
 
52
- def current_person
53
- @current_person ||= login_from_cas unless @current_person == false
54
- end
55
-
56
- def login_from_cas
57
- if session[:cas_user]
58
- person = Person.find_by_name(session[:cas_user])
59
- logout_killing_session! unless person
60
- person
55
+ def current_user
56
+ if session[:cas_user] && @user.nil?
57
+ @user = User.find_by_name(session[:cas_user])
58
+ logout_killing_session! unless @user
61
59
  end
60
+ @user
62
61
  end
63
62
 
64
- - Add the following to you logout action
63
+ - Your logout action could look like:
65
64
 
66
- Casablanca::RailsFilter.logout(self)
65
+ def logout
66
+ Casablanca::Rails::Filter.logout(self)
67
+ redirect_to Casablanca::RailsFilter.logout_url(self)
68
+ end
69
+
67
70
 
68
71
  == REQUIREMENTS:
69
72
 
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'hoe'
5
5
  require 'lib/casablanca.rb'
6
6
 
7
7
  Hoe.new('casablanca', Casablanca::VERSION) do |p|
8
- p.developer('FIX', 'FIX@example.com')
8
+ p.developer('Petrik de Heus', 'FIX@example.com')
9
9
  p.remote_rdoc_dir = '' # Release to root
10
10
  end
11
11
 
data/lib/casablanca.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Casablanca
2
- VERSION = '0.0.3.1'
2
+ VERSION = '0.1.1'
3
3
  end
4
4
  require 'casablanca/client'
5
5
  require 'casablanca/response_parsers'
@@ -28,7 +28,9 @@ module Casablanca
28
28
  def login_url(params={})
29
29
  uri = URI.parse("#{@cas_server_url}/login")
30
30
  query = {:service => @service_url}
31
+ # TODO Check that only one of these can be set
31
32
  query[:renew] = 'true' if params[:renew]
33
+ query[:gateway] = 'true' if params[:gateway]
32
34
  uri.merge_query(query)
33
35
  uri.to_s
34
36
  end
@@ -0,0 +1,2 @@
1
+ class CasProxyCallbackController < ActionController::Base
2
+ end
@@ -0,0 +1,157 @@
1
+ module Casablanca::Rails
2
+
3
+ class Config
4
+
5
+ class << self
6
+
7
+ ##
8
+ # Configure the client
9
+ #
10
+ # Casablanca::Rails::Config.config do |config|
11
+ # config[:cas_server_url] = "http://localhost:4567"
12
+ # # Always require new credentials for authentication
13
+ # config[:renew] = true
14
+ # end
15
+ def config
16
+ config = {}
17
+ yield config
18
+ @cas_server_url = config[:cas_server_url]
19
+ @renew = config[:renew] # always renew the session
20
+ # set logger to rails logger
21
+ Casablanca::Client.logger = ::ActionController::Base.logger
22
+ end
23
+
24
+ def renew
25
+ @renew
26
+ end
27
+
28
+ def cas_server_url
29
+ @cas_server_url
30
+ end
31
+
32
+ end
33
+ end
34
+
35
+ class Filter
36
+
37
+ class << self
38
+
39
+ ##
40
+ # Require a authenticated user to the CAS server otherwise redirect to
41
+ # the CAS server login url.
42
+ # Set session[:cas_user] to the authenticated CAS user if authenticated
43
+ def filter(controller)
44
+ if authentication_required?(controller)
45
+ return get_credentials(controller)
46
+ elsif controller.params[:ticket]
47
+ return authenticate_ticket(controller)
48
+ else
49
+ return true
50
+ end
51
+ end
52
+
53
+ ##
54
+ # The login url of the Cas server. This page has the login form.
55
+ def login_url(controller, params={})
56
+ client = Casablanca::Client.new(:cas_server_url => Config.cas_server_url, :service_url => service_url(controller))
57
+ client.login_url(params)
58
+ end
59
+
60
+ ##
61
+ # The logout url of the Cas server.
62
+ def logout_url(controller, params={})
63
+ client = Casablanca::Client.new(:cas_server_url => Config.cas_server_url, :service_url => service_url(controller))
64
+ client.logout_url(params)
65
+ end
66
+
67
+ ##
68
+ # Logs out of the Cas server.
69
+ def logout(controller)
70
+ controller.session[:cas_user] = nil
71
+ end
72
+
73
+ def logger
74
+ Casablanca::Client.logger
75
+ end
76
+
77
+ # Always require new credentials for authentication?
78
+ def renew?
79
+ Config.renew
80
+ end
81
+
82
+ # Has the user already talked to the Cas server?
83
+ def authentication_required?(controller)
84
+ (controller.session[:cas_user].nil? || renew?) && controller.params[:ticket].nil?
85
+ end
86
+
87
+ def redirect_to_cas_login(controller, renew)
88
+ controller.session[:cas_renew] = renew
89
+ controller.send(:redirect_to, login_url(controller, :renew => renew))
90
+ end
91
+
92
+ def get_credentials(controller)
93
+ if renew?
94
+ logger.debug "Always require credentials for authentication"
95
+ else
96
+ logger.debug "Not authenticated yet. Ticket parameter required"
97
+ end
98
+ redirect_to_cas_login(controller, renew?)
99
+ return false
100
+ end
101
+
102
+ def authenticate_ticket(controller)
103
+ client = Casablanca::Client.new(:cas_server_url => Config.cas_server_url, :service_url => service_url(controller))
104
+ ticket = Casablanca::Ticket.new(controller.params[:ticket], client.service_url, controller.session[:cas_renew])
105
+ if client.authenticate_ticket(ticket)
106
+ logger.debug "Ticket authenticated"
107
+ controller.session[:cas_user] = ticket.user
108
+ controller.session[:cas_renew] = nil
109
+ return true
110
+ else
111
+ logger.debug "Ticket authentication failed: #{ticket.failure_message}"
112
+ logout(controller)
113
+ logger.debug "Renew login credentials"
114
+ redirect_to_cas_login(controller, renew?)
115
+ return false
116
+ end
117
+ end
118
+
119
+ private
120
+
121
+ def service_url(controller)
122
+ params = controller.params.merge(:only_path => false).dup
123
+ params.delete(:ticket)
124
+ controller.url_for(params)
125
+ end
126
+
127
+ end
128
+ end
129
+
130
+
131
+ class GatewayFilter < Filter
132
+
133
+ class << self
134
+
135
+ # # Has the user already talked to the Cas server?
136
+ # def authentication_required?(controller)
137
+ # super(controller)
138
+ # end
139
+
140
+ def get_credentials(controller)
141
+ if controller.session[:cas_gatewayed]
142
+ logger.debug "Allow user without credentials because gateway is set"
143
+ return true
144
+ end
145
+ return super(controller)
146
+ end
147
+
148
+ def redirect_to_cas_login(controller, renew)
149
+ controller.session[:cas_gatewayed] = true
150
+ logger.debug "Redirecting to #{login_url(controller, :gateway => true)}"
151
+ controller.send(:redirect_to, login_url(controller, :gateway => true))
152
+ end
153
+
154
+ end
155
+ end
156
+
157
+ end
data/test/mocks.rb CHANGED
@@ -24,7 +24,7 @@ module ActionController
24
24
  class Base
25
25
  def self.logger
26
26
  @logger = ::Logger.new($stderr)
27
- @logger.level = ::Logger::ERROR
27
+ @logger.level = LOGGER_LEVEL
28
28
  @logger
29
29
  end
30
30
  end
@@ -41,6 +41,9 @@ class Controller < ActionController::Base
41
41
  end
42
42
 
43
43
  def url_for(url)
44
+ if url.is_a? Hash
45
+ return "http://localhost:3000" if url[:only_path] == false
46
+ end
44
47
  url
45
48
  end
46
49
 
data/test/test_client.rb CHANGED
@@ -92,9 +92,9 @@ class TestCommandLineClient < Test::Unit::TestCase
92
92
  mock_get_service_ticket(@client)
93
93
  service_ticket = @client.login('admin', 'admin')
94
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
95
+ if MOCK_REQUESTS
96
+ @client.expects(:get).returns(MockResponse.new('<html></html>', '200', :location => 'http://localhost:3000?ticket=ST-1231341579r871C5757B79767C21E'))
97
+ end
98
98
  service_ticket = @client.logout
99
99
  assert_equal nil, @client.ticket_granting_ticket
100
100
  end
@@ -103,9 +103,9 @@ class TestCommandLineClient < Test::Unit::TestCase
103
103
  mock_get_service_ticket(@client)
104
104
  service_ticket = @client.login('admin', 'admin')
105
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
106
+ if MOCK_REQUESTS
107
+ @client.expects(:get).returns(MockResponse.new('<html></html>', '200', :location => 'http://localhost:3000?ticket=ST-1231341579r871C5757B79767C21E'))
108
+ end
109
109
  service_ticket = @client.logout('follow_url')
110
110
  assert_equal nil, @client.ticket_granting_ticket
111
111
  # TODO check for follow_url
data/test/test_helper.rb CHANGED
@@ -1,13 +1,16 @@
1
1
  require 'test/unit'
2
2
  require 'rubygems'
3
3
  require 'mocha'
4
+ # require 'logger'
4
5
  require(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'casablanca.rb')))
6
+ require(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'casablanca', 'client.rb')))
5
7
  require(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'casablanca', 'rails', 'filter.rb')))
6
8
  require(File.expand_path(File.join(File.dirname(__FILE__), 'mocks.rb')))
7
9
  require(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'casablanca', 'rails', 'cas_proxy_callback_controller.rb')))
8
10
 
9
11
  # set to false if you're integration testing against a real server
10
- MOCK_REQUESTS = true
12
+ MOCK_REQUESTS = true unless defined? MOCK_REQUESTS
13
+ LOGGER_LEVEL = Logger::WARN unless defined? LOGGER_LEVEL
11
14
 
12
15
  class Test::Unit::TestCase
13
16
  include Casablanca
@@ -33,6 +36,7 @@ class Test::Unit::TestCase
33
36
  end
34
37
  end
35
38
 
39
+ unless defined? VALID_REQUEST
36
40
  VALID_REQUEST = %(
37
41
  <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
38
42
  <cas:authenticationSuccess>
@@ -55,4 +59,5 @@ INVALID_TICKET = %(
55
59
  Ticket ST-1231242314r72465638160B31E8D1 not recognized.
56
60
  </cas:authenticationFailure>
57
61
  </cas:serviceResponse>
58
- )
62
+ )
63
+ end
@@ -1,53 +1,59 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper.rb')
1
+ require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
+
3
+ class TestRailsConfig < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @controller = Controller.new
7
+ @controller.params = {}
8
+ end
9
+
10
+ def test_config
11
+ Rails::Config.config do |config|
12
+ config[:cas_server_url] = "http://example.com/cas_server"
13
+ config[:renew] = true
14
+ end
15
+ assert_equal 'http://example.com/cas_server/login?service=http%3A%2F%2Flocalhost%3A3000', Rails::Filter.login_url(@controller)
16
+ assert_equal true, Rails::Filter.renew?
17
+ end
18
+
19
+ end
2
20
 
3
21
  class TestRailsFilter < Test::Unit::TestCase
22
+ include Casablanca::Rails
4
23
  def setup
5
- Casablanca::RailsFilter.config do |config|
24
+ Config.config do |config|
6
25
  config[:cas_server_url] = "http://localhost:4567"
7
- config[:service_url] = "http://localhost:3000"
8
26
  end
9
27
  @controller = Controller.new
10
- @controller.params = {}
28
+ @controller.params = {}
11
29
  end
12
30
 
13
31
  def test_login_url
14
- assert_equal 'http://localhost:4567/login?service=http%3A%2F%2Flocalhost%3A3000', RailsFilter.login_url
32
+ assert_equal 'http://localhost:4567/login?service=http%3A%2F%2Flocalhost%3A3000', Filter.login_url(@controller)
15
33
  end
16
34
 
17
35
  def test_login_url_with_params
18
- url = RailsFilter.login_url(:renew => true)
36
+ url = Filter.login_url(@controller, :renew => true)
19
37
  assert_equal true, (url =~ /service\=http%3A%2F%2Flocalhost%3A3000/) > 0
20
38
  assert_equal true, (url =~ /renew\=true/) > 0
21
39
  end
22
40
 
23
41
  def test_logout_url
24
- assert_equal 'http://localhost:4567/logout?', RailsFilter.logout_url
42
+ assert_equal 'http://localhost:4567/logout?', Filter.logout_url(@controller)
25
43
  end
26
44
 
27
45
  def test_logout
28
46
  @controller.session = { :cas_user => 'admin' }
29
- RailsFilter.logout(@controller)
47
+ Filter.logout(@controller)
30
48
  assert_equal({:cas_user=>nil }, @controller.session)
31
49
  end
32
-
33
- def test_config
34
- Casablanca::RailsFilter.config do |config|
35
- config[:cas_server_url] = "http://example.com/cas_server"
36
- config[:service_url] = "http://example.com/application"
37
- config[:renew] = true
38
- end
39
- # assert_equal "http://example.com/cas_server", RailsFilter.client.cas_server_url
40
- # assert_equal "http://example.com/application", RailsFilter.client.service_url
41
- assert_equal 'http://example.com/cas_server/login?service=http%3A%2F%2Fexample.com%2Fapplication', RailsFilter.login_url
42
- assert_equal true, RailsFilter.renew?
43
- end
44
50
 
45
51
  def test_filter_invalid_attempt
46
52
  service_ticket = get_service_ticket
47
53
  params = {:ticket => 'service_ticket.ticket'}
48
54
  mock_authenticate_ticket(INVALID_REQUEST)
49
55
  @controller.params = params
50
- assert_equal false, RailsFilter.filter(@controller)
56
+ assert_equal false, Filter.filter(@controller)
51
57
  end
52
58
 
53
59
  def test_filter_authenticated_with_valid_ticket_from_request
@@ -55,24 +61,60 @@ class TestRailsFilter < Test::Unit::TestCase
55
61
  params = {:ticket => service_ticket.ticket}
56
62
  mock_authenticate_ticket(VALID_REQUEST)
57
63
  @controller.params = params
58
- assert_equal true, RailsFilter.filter(@controller)
64
+ assert_equal true, Filter.filter(@controller)
59
65
  assert_equal 'admin', @controller.session[:cas_user]
60
66
  end
61
67
 
62
68
  def test_filter_already_authenticated_with_valid_ticket_from_session
63
69
  service_ticket = get_service_ticket
64
70
  @controller.session = {:cas_user => 'admin'}
65
- mock_authenticate_ticket(VALID_REQUEST)
66
- assert_equal true, RailsFilter.filter(@controller)
71
+ assert_equal true, Filter.filter(@controller)
67
72
  assert_equal 'admin', @controller.session[:cas_user]
68
73
  end
74
+
75
+ def test_filter_already_authenticated_with_valid_ticket_from_session_but_renew_required
76
+ Config.config do |config|
77
+ config[:cas_server_url] = "http://localhost:4567"
78
+ config[:renew] = true
79
+ end
80
+ service_ticket = get_service_ticket
81
+ @controller.session = {:cas_user => 'admin'}
82
+ assert_equal false, Filter.filter(@controller)
83
+ assert_equal 'admin', @controller.session[:cas_user]
84
+ end
69
85
 
70
86
  def test_filter_not_authenticated
71
- assert_equal false, RailsFilter.filter(@controller)
87
+ assert_equal false, Filter.filter(@controller)
72
88
  end
73
89
 
74
90
  def test_filter_not_authenticated
75
- assert_equal false, RailsFilter.filter(@controller)
91
+ assert_equal false, Filter.filter(@controller)
92
+ end
93
+
94
+ end
95
+
96
+ class TestRailsGatewayFilter < TestRailsFilter
97
+ def setup
98
+ Config.config do |config|
99
+ config[:cas_server_url] = "http://localhost:4567"
100
+ end
101
+ @controller = Controller.new
102
+ @controller.params = {}
103
+ end
104
+
105
+ def test_filter_not_authenticated_sets_cas_gatewayed
106
+ # service_ticket = get_service_ticket
107
+ #mock_authenticate_ticket(VALID_REQUEST)
108
+ assert_equal false, GatewayFilter.filter(@controller)
109
+ assert_equal true, @controller.session[:cas_gatewayed]
110
+ end
111
+
112
+ def test_filter_not_authenticated_already_tried
113
+ # service_ticket = get_service_ticket
114
+ @controller.session = {:cas_gatewayed => true}
115
+ #mock_authenticate_ticket(VALID_REQUEST)
116
+ assert_equal true, GatewayFilter.filter(@controller)
117
+ assert_equal nil, @controller.session[:cas_user]
76
118
  end
77
119
 
78
120
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: p8-casablanca
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Petrik de Heus
@@ -9,19 +9,20 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-24 00:00:00 -08:00
12
+ date: 2009-02-18 00:00:00 -08:00
13
13
  default_executable: casablanca
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: hoe
17
+ type: :development
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
20
21
  - - ">="
21
22
  - !ruby/object:Gem::Version
22
- version: 1.8.2
23
+ version: 1.8.3
23
24
  version:
24
- description:
25
+ description: Casablanca is a ruby single sign-on client for the CAS 2.0 protocol.
25
26
  email:
26
27
  - FIX@example.com
27
28
  executables:
@@ -35,24 +36,25 @@ extra_rdoc_files:
35
36
  files:
36
37
  - History.txt
37
38
  - Manifest.txt
39
+ - README.txt
38
40
  - Rakefile
39
- - init.rb
40
41
  - bin/casablanca
42
+ - init.rb
41
43
  - lib/casablanca.rb
42
44
  - lib/casablanca/cli.rb
43
45
  - lib/casablanca/client.rb
44
- - lib/casablanca/filters/rails.rb
46
+ - lib/casablanca/rails/cas_proxy_callback_controller.rb
47
+ - lib/casablanca/rails/filter.rb
45
48
  - lib/casablanca/response_parsers.rb
46
49
  - test/mocks.rb
47
50
  - test/test_client.rb
48
51
  - test/test_helper.rb
49
52
  - test/test_parser.rb
53
+ - test/test_rails_cas_proxy_callback_controller.rb
50
54
  - test/test_rails_filter.rb
51
55
  - test/test_ticket.rb
52
- - test/test_rails_cas_proxy_callback_controller.rb
53
- - README.txt
54
56
  has_rdoc: true
55
- homepage:
57
+ homepage: http://rubyforge.org/projects/casablanca/
56
58
  post_install_message:
57
59
  rdoc_options:
58
60
  - --main
@@ -77,12 +79,11 @@ rubyforge_project: casablanca
77
79
  rubygems_version: 1.2.0
78
80
  signing_key:
79
81
  specification_version: 2
80
- summary: A single sign-on client for the CAS 2.0 protocol
82
+ summary: Casablanca is a ruby single sign-on client for the CAS 2.0 protocol.
81
83
  test_files:
82
- - test/mocks.rb
83
84
  - test/test_client.rb
84
85
  - test/test_helper.rb
85
86
  - test/test_parser.rb
87
+ - test/test_rails_cas_proxy_callback_controller.rb
86
88
  - test/test_rails_filter.rb
87
89
  - test/test_ticket.rb
88
- - test/test_rails_cas_proxy_callback_controller.rb