rubycas-server 0.7.1.1 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. data/CHANGELOG +292 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE +26 -0
  4. data/README.md +36 -0
  5. data/Rakefile +0 -3
  6. data/bin/rubycas-server +24 -19
  7. data/lib/casserver.rb +7 -110
  8. data/lib/casserver/authenticators/active_directory_ldap.rb +8 -0
  9. data/lib/casserver/authenticators/active_resource.rb +125 -0
  10. data/lib/casserver/authenticators/authlogic_crypto_providers/aes256.rb +43 -0
  11. data/lib/casserver/authenticators/authlogic_crypto_providers/bcrypt.rb +92 -0
  12. data/lib/casserver/authenticators/authlogic_crypto_providers/md5.rb +34 -0
  13. data/lib/casserver/authenticators/authlogic_crypto_providers/sha1.rb +59 -0
  14. data/lib/casserver/authenticators/authlogic_crypto_providers/sha512.rb +50 -0
  15. data/lib/casserver/authenticators/base.rb +30 -11
  16. data/lib/casserver/authenticators/client_certificate.rb +7 -6
  17. data/lib/casserver/authenticators/google.rb +13 -9
  18. data/lib/casserver/authenticators/ldap.rb +37 -28
  19. data/lib/casserver/authenticators/ntlm.rb +9 -9
  20. data/lib/casserver/authenticators/open_id.rb +3 -3
  21. data/lib/casserver/authenticators/sql.rb +65 -34
  22. data/lib/casserver/authenticators/sql_authlogic.rb +93 -0
  23. data/lib/casserver/authenticators/sql_encrypted.rb +44 -44
  24. data/lib/casserver/authenticators/sql_md5.rb +2 -2
  25. data/lib/casserver/authenticators/sql_rest_auth.rb +82 -0
  26. data/lib/casserver/authenticators/test.rb +10 -7
  27. data/lib/casserver/cas.rb +94 -94
  28. data/lib/casserver/localization.rb +91 -0
  29. data/lib/casserver/model.rb +270 -0
  30. data/lib/casserver/server.rb +745 -0
  31. data/lib/casserver/utils.rb +9 -7
  32. data/lib/casserver/views/_login_form.erb +42 -0
  33. data/lib/casserver/views/layout.erb +18 -0
  34. data/lib/casserver/views/login.erb +30 -0
  35. data/lib/casserver/views/proxy.builder +12 -0
  36. data/lib/casserver/views/proxy_validate.builder +25 -0
  37. data/lib/casserver/views/service_validate.builder +18 -0
  38. data/lib/casserver/views/validate.erb +2 -0
  39. data/po/de_DE/rubycas-server.po +127 -0
  40. data/po/es_ES/rubycas-server.po +123 -0
  41. data/po/fr_FR/rubycas-server.po +128 -0
  42. data/po/ja_JP/rubycas-server.po +126 -0
  43. data/po/pl_PL/rubycas-server.po +123 -0
  44. data/po/pt_BR/rubycas-server.po +123 -0
  45. data/po/ru_RU/rubycas-server.po +118 -0
  46. data/po/rubycas-server.pot +112 -0
  47. data/po/zh_CN/rubycas-server.po +113 -0
  48. data/po/zh_TW/rubycas-server.po +113 -0
  49. data/public/themes/cas.css +121 -0
  50. data/{lib → public}/themes/notice.png +0 -0
  51. data/{lib → public}/themes/ok.png +0 -0
  52. data/{lib → public}/themes/simple/bg.png +0 -0
  53. data/public/themes/simple/favicon.png +0 -0
  54. data/{lib → public}/themes/simple/login_box_bg.png +0 -0
  55. data/{lib → public}/themes/simple/logo.png +0 -0
  56. data/public/themes/simple/theme.css +28 -0
  57. data/{lib → public}/themes/urbacon/bg.png +0 -0
  58. data/{lib → public}/themes/urbacon/login_box_bg.png +0 -0
  59. data/{lib → public}/themes/urbacon/logo.png +0 -0
  60. data/public/themes/urbacon/theme.css +33 -0
  61. data/{lib → public}/themes/warning.png +0 -0
  62. data/resources/init.d.sh +1 -1
  63. data/rubycas-server.gemspec +57 -0
  64. data/setup.rb +4 -4
  65. data/spec/alt_config.yml +50 -0
  66. data/spec/authenticators/active_resource_spec.rb +109 -0
  67. data/spec/authenticators/ldap_spec.rb +53 -0
  68. data/spec/casserver_spec.rb +149 -0
  69. data/spec/default_config.yml +50 -0
  70. data/spec/model_spec.rb +42 -0
  71. data/spec/spec.opts +4 -0
  72. data/spec/spec_helper.rb +88 -0
  73. data/spec/utils_spec.rb +53 -0
  74. data/tasks/bundler.rake +4 -0
  75. data/tasks/db/migrate.rake +12 -0
  76. data/tasks/localization.rake +13 -0
  77. data/tasks/spec.rake +10 -0
  78. metadata +294 -91
  79. data/CHANGELOG.txt +0 -1
  80. data/History.txt +0 -252
  81. data/LICENSE.txt +0 -504
  82. data/Manifest.txt +0 -72
  83. data/PostInstall.txt +0 -3
  84. data/README.txt +0 -25
  85. data/bin/rubycas-server-ctl +0 -22
  86. data/config.example.yml +0 -442
  87. data/config/hoe.rb +0 -76
  88. data/config/requirements.rb +0 -15
  89. data/custom_views.example.rb +0 -11
  90. data/lib/casserver/conf.rb +0 -112
  91. data/lib/casserver/controllers.rb +0 -452
  92. data/lib/casserver/environment.rb +0 -30
  93. data/lib/casserver/models.rb +0 -218
  94. data/lib/casserver/postambles.rb +0 -174
  95. data/lib/casserver/version.rb +0 -9
  96. data/lib/casserver/views.rb +0 -243
  97. data/lib/rubycas-server.rb +0 -1
  98. data/lib/rubycas-server/version.rb +0 -1
  99. data/lib/themes/cas.css +0 -121
  100. data/lib/themes/simple/theme.css +0 -28
  101. data/lib/themes/urbacon/theme.css +0 -33
  102. data/misc/basic_cas_single_signon_mechanism_diagram.png +0 -0
  103. data/misc/basic_cas_single_signon_mechanism_diagram.svg +0 -652
  104. data/script/console +0 -10
  105. data/script/destroy +0 -14
  106. data/script/generate +0 -14
  107. data/script/txt2html +0 -82
  108. data/tasks/deployment.rake +0 -34
  109. data/tasks/environment.rake +0 -7
  110. data/tasks/website.rake +0 -17
  111. data/vendor/isaac_0.9.1/LICENSE +0 -26
  112. data/vendor/isaac_0.9.1/README +0 -78
  113. data/vendor/isaac_0.9.1/TODO +0 -3
  114. data/vendor/isaac_0.9.1/VERSIONS +0 -3
  115. data/vendor/isaac_0.9.1/crypt/ISAAC.rb +0 -171
  116. data/vendor/isaac_0.9.1/isaac.gemspec +0 -39
  117. data/vendor/isaac_0.9.1/setup.rb +0 -596
  118. data/vendor/isaac_0.9.1/test/TC_ISAAC.rb +0 -76
  119. data/website/index.html +0 -40
  120. data/website/index.txt +0 -3
  121. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  122. data/website/stylesheets/screen.css +0 -138
  123. data/website/template.html.erb +0 -40
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,28 @@
1
+ body {
2
+ background-image: url(bg.png);
3
+ }
4
+
5
+ #headline-container {
6
+ margin-bottom: 5px;
7
+ }
8
+
9
+ #login-box {
10
+ margin: 0 auto;
11
+ width: 450px;
12
+ top: 110px;
13
+ position: relative;
14
+ }
15
+
16
+ #login-form {
17
+ background-color: #fff;
18
+ border: 1px #aaa solid;
19
+ }
20
+
21
+ #logo-container {
22
+ vertical-align: middle;
23
+ }
24
+
25
+ #logo {
26
+ width: 128px;
27
+ height: 128px;
28
+ }
File without changes
File without changes
@@ -0,0 +1,33 @@
1
+ body {
2
+ background-image: url(bg.png);
3
+ }
4
+
5
+ label {
6
+ color: #5c6156;
7
+ }
8
+
9
+ #login-form {
10
+ background-repeat: no-repeat;
11
+ background-image: url(login_box_bg.png);
12
+ height: 175px;
13
+ width: 210px;
14
+ padding: 20px;
15
+ }
16
+
17
+ #logo-container {
18
+ vertical-align: top;
19
+ }
20
+
21
+ #logo {
22
+ width: 115px;
23
+ height: 171px;
24
+ }
25
+
26
+ #infoline {
27
+ color: #5c6156;
28
+ font-size: 8px;
29
+ }
30
+
31
+ #headline-container {
32
+ margin-right: 15px;
33
+ }
File without changes
@@ -1,6 +1,6 @@
1
1
  #! /bin/sh
2
2
  #
3
- # Copyright (c) 2007 Urbacon Ltd.
3
+ # Copyright (c) 2008 Urbacon Ltd.
4
4
  #
5
5
  # System startup script for the RubyCAS-Server
6
6
  #
@@ -0,0 +1,57 @@
1
+
2
+ $gemspec = Gem::Specification.new do |s|
3
+ s.name = 'rubycas-server'
4
+ s.version = '1.0'
5
+ s.authors = ["Matt Zukowski"]
6
+ s.email = ["matt@zukowski.ca"]
7
+ s.homepage = 'http://code.google.com/p/rubycas-server/'
8
+ s.platform = Gem::Platform::RUBY
9
+ s.summary = %q{Provides single sign-on authentication for web applications using the CAS protocol.}
10
+ s.description = %q{Provides single sign-on authentication for web applications using the CAS protocol.}
11
+
12
+ s.files = [
13
+ "CHANGELOG", "LICENSE", "README.md", "Rakefile", "setup.rb",
14
+ "bin/*", "db/*", "lib/**/*.rb", "public/**/*", "po/**/*", "mo/**/*", "resources/*.*",
15
+ "tasks/**/*.rake", "vendor/**/*", "script/*", "lib/**/*.erb", "lib/**/*.builder",
16
+ "Gemfile", "rubycas-server.gemspec"
17
+ ].map{|p| Dir[p]}.flatten
18
+
19
+ s.test_files = `git ls-files -- spec`.split("\n")
20
+
21
+ s.executables = ["rubycas-server"]
22
+ s.bindir = "bin"
23
+ s.require_path = "lib"
24
+
25
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md"]
26
+
27
+ s.has_rdoc = true
28
+ s.post_install_message = %q{
29
+ For more information on RubyCAS-Server, see http://code.google.com/p/rubycas-server
30
+
31
+ If you plan on using RubyCAS-Server with languages other than English, please cd into the
32
+ RubyCAS-Server installation directory (where the gem is installed) and type `rake localization:mo`
33
+ to build the LOCALE_LC files.
34
+
35
+ }
36
+
37
+ s.add_dependency("activerecord", "~> 2.3.6")
38
+ s.add_dependency("activesupport", "~> 2.3.6")
39
+ s.add_dependency("sinatra", "~> 1.0")
40
+ s.add_dependency("gettext", "~> 2.1.0")
41
+ s.add_dependency("crypt-isaac", "~> 0.9.1")
42
+
43
+ s.add_development_dependency("rack-test")
44
+ s.add_development_dependency("capybara")
45
+ s.add_development_dependency("rspec")
46
+ s.add_development_dependency("rspec-core")
47
+ s.add_development_dependency("sqlite3", "~> 1.3.1")
48
+
49
+ # for authenticator specs
50
+ s.add_development_dependency("net-ldap", "~> 0.1.1")
51
+ s.add_development_dependency("activeresource", "~> 2.3.6")
52
+
53
+ s.rdoc_options = [
54
+ '--quiet', '--title', 'RubyCAS-Server Documentation', '--opname',
55
+ 'index.html', '--line-numbers', '--main', 'README.md', '--inline-source'
56
+ ]
57
+ end
data/setup.rb CHANGED
@@ -659,7 +659,7 @@ module FileOperations
659
659
  def ruby(*args)
660
660
  command config('rubyprog'), *args
661
661
  end
662
-
662
+
663
663
  def make(task = nil)
664
664
  command(*[config('makeprog'), task].compact)
665
665
  end
@@ -722,7 +722,7 @@ module HookScriptAPI
722
722
  def srcdirectory?(path)
723
723
  File.dir?(srcfile(path))
724
724
  end
725
-
725
+
726
726
  def srcfile?(path)
727
727
  File.file?(srcfile(path))
728
728
  end
@@ -826,7 +826,7 @@ class ToplevelInstaller
826
826
  __send__ "exec_#{task}"
827
827
  end
828
828
  end
829
-
829
+
830
830
  def run_metaconfigs
831
831
  @config.load_script "#{@ardir}/metaconfig"
832
832
  end
@@ -1404,7 +1404,7 @@ class Installer
1404
1404
  end
1405
1405
 
1406
1406
  # picked up many entries from cvs-1.11.1/src/ignore.c
1407
- JUNK_FILES = %w(
1407
+ JUNK_FILES = %w(
1408
1408
  core RCSLOG tags TAGS .make.state
1409
1409
  .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1410
1410
  *~ *.old *.bak *.BAK *.orig *.rej _$* *$
@@ -0,0 +1,50 @@
1
+ server: webrick
2
+ port: 6543
3
+ #ssl_cert: test.pem
4
+ uri_path: /test
5
+ #bind_address: 0.0.0.0
6
+
7
+ # database:
8
+ # adapter: mysql
9
+ # database: casserver
10
+ # username: root
11
+ # password:
12
+ # host: localhost
13
+ # reconnect: true
14
+ database:
15
+ adapter: sqlite3
16
+ database: spec/casserver_spec.db
17
+
18
+ disable_auto_migrations: true
19
+
20
+ quiet: true
21
+
22
+ authenticator:
23
+ class: CASServer::Authenticators::Test
24
+ password: spec_password
25
+
26
+ theme: simple
27
+
28
+ organization: "RSPEC-TEST"
29
+
30
+ infoline: "This is an rspec test."
31
+
32
+ #custom_views: /path/to/custom/views
33
+
34
+ default_locale: en
35
+
36
+ log:
37
+ file: casserver_spec.log
38
+ level: DEBUG
39
+
40
+ #db_log:
41
+ # file: casserver_spec_db.log
42
+
43
+ enable_single_sign_out: true
44
+
45
+ #maximum_unused_login_ticket_lifetime: 300
46
+ #maximum_unused_service_ticket_lifetime: 300
47
+
48
+ #maximum_session_lifetime: 172800
49
+
50
+ #downcase_username: true
@@ -0,0 +1,109 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+
4
+ require 'casserver/authenticators/active_resource'
5
+
6
+ describe CASServer::Authenticators::Helpers::Identity do
7
+
8
+ it { should be_an ActiveResource::Base }
9
+
10
+ it "class should respond to :authenticate" do
11
+ subject.class.should respond_to :authenticate
12
+ end
13
+
14
+ it "class should have a method_name accessor" do
15
+ CASServer::Authenticators::Helpers::Identity.method_name.should == :authenticate
16
+ end
17
+
18
+ it "class should have a method_name accessor" do
19
+ CASServer::Authenticators::Helpers::Identity.method_type.should == :post
20
+ end
21
+
22
+ it "class method_type accessor should validate type" do
23
+ expect {
24
+ CASServer::Authenticators::Helpers::Identity.method_type = :foo
25
+ }.to raise_error(ArgumentError)
26
+ end
27
+
28
+ end
29
+
30
+ describe CASServer::Authenticators::ActiveResource do
31
+
32
+ describe "#setup" do
33
+
34
+ it "should configure the identity object" do
35
+ CASServer::Authenticators::Helpers::Identity.should_receive(:user=).with('httpuser').once
36
+ CASServer::Authenticators::ActiveResource.setup :site => 'http://api.example.org', :user => 'httpuser'
37
+ end
38
+
39
+ it "should configure the method_type" do
40
+ CASServer::Authenticators::Helpers::Identity.should_receive(:method_type=).with('get').once
41
+ CASServer::Authenticators::ActiveResource.setup :site => 'http://api.example.org', :method_type => 'get'
42
+ end
43
+
44
+ it "should raise if site option is missing" do
45
+ expect {
46
+ CASServer::Authenticators::ActiveResource.setup({}).should
47
+ }.to raise_error(CASServer::AuthenticatorError, /site option/)
48
+ end
49
+ end
50
+
51
+ describe "#validate" do
52
+
53
+ let(:credentials) { {:username => 'validusername',
54
+ :password => 'validpassword',
55
+ :service => 'test.service'} }
56
+
57
+ let(:auth) { CASServer::Authenticators::ActiveResource.new }
58
+
59
+ def mock_authenticate identity = nil
60
+ identity = CASServer::Authenticators::Helpers::Identity.new if identity.nil?
61
+ CASServer::Authenticators::Helpers::Identity.stub!(:authenticate).and_return(identity)
62
+ end
63
+
64
+ def sample_identity attrs = {}
65
+ identity = CASServer::Authenticators::Helpers::Identity.new
66
+ attrs.each { |k,v| identity.send "#{k}=", v }
67
+ identity
68
+ end
69
+
70
+ it "should call Identity#autenticate with the given params" do
71
+ CASServer::Authenticators::Helpers::Identity.should_receive(:authenticate).with(credentials).once
72
+ auth.validate(credentials)
73
+ end
74
+
75
+ it "should return identity object attributes as extra attributes" do
76
+ auth.configure({}.with_indifferent_access)
77
+ identity = sample_identity({:email => 'foo@example.org'})
78
+ mock_authenticate identity
79
+ auth.validate(credentials).should be_true
80
+ auth.extra_attributes.should == identity.attributes
81
+ end
82
+
83
+ it "should return false when http raises" do
84
+ CASServer::Authenticators::Helpers::Identity.stub!(:authenticate).and_raise(ActiveResource::ForbiddenAccess.new({}))
85
+ auth.validate(credentials).should be_false
86
+ end
87
+
88
+ it "should apply extra_attribute filter" do
89
+ auth.configure({ :extra_attributes => 'age'}.with_indifferent_access)
90
+ mock_authenticate sample_identity({ :email => 'foo@example.org', :age => 28 })
91
+ auth.validate(credentials).should be_true
92
+ auth.extra_attributes.should == { "age" => "28" }
93
+ end
94
+
95
+ it "should only extract not filtered attributes" do
96
+ auth.configure({ :filter_attributes => 'age'}.with_indifferent_access)
97
+ mock_authenticate sample_identity({ :email => 'foo@example.org', :age => 28 })
98
+ auth.validate(credentials).should be_true
99
+ auth.extra_attributes.should == { "email" => 'foo@example.org' }
100
+ end
101
+
102
+ it "should filter password if filter attributes is not given" do
103
+ auth.configure({}.with_indifferent_access)
104
+ mock_authenticate sample_identity({ :email => 'foo@example.org', :password => 'secret' })
105
+ auth.validate(credentials).should be_true
106
+ auth.extra_attributes.should == { "email" => 'foo@example.org' }
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+
4
+ require 'casserver/authenticators/ldap'
5
+
6
+ describe CASServer::Authenticators::LDAP do
7
+ before do
8
+ @ldap_entry = mock(Net::LDAP::Entry.new)
9
+ @ldap_entry.stub!(:[]).and_return("Test")
10
+
11
+ @ldap = mock(Net::LDAP)
12
+ @ldap.stub!(:host=)
13
+ @ldap.stub!(:port=)
14
+ @ldap.stub!(:encryption)
15
+ @ldap.stub!(:bind_as).and_return(true)
16
+ @ldap.stub!(:authenticate).and_return(true)
17
+ @ldap.stub!(:search).and_return([@ldap_entry])
18
+
19
+ Net::LDAP.stub!(:new).and_return(@ldap)
20
+ end
21
+
22
+ describe '#validate' do
23
+
24
+ it 'validate with preauthentication and with extra attributes' do
25
+ auth = CASServer::Authenticators::LDAP.new
26
+
27
+ auth_config = HashWithIndifferentAccess.new(
28
+ :ldap => {
29
+ :host => "ad.example.net",
30
+ :port => 389,
31
+ :base => "dc=example,dc=net",
32
+ :filter => "(objectClass=person)",
33
+ :auth_user => "authenticator",
34
+ :auth_password => "itsasecret"
35
+ },
36
+ :extra_attributes => [:full_name, :address]
37
+ )
38
+
39
+ auth.configure(auth_config.merge('auth_index' => 0))
40
+ auth.validate(
41
+ :username => 'validusername',
42
+ :password => 'validpassword',
43
+ :service => 'test.service',
44
+ :request => {}
45
+ ).should == true
46
+
47
+ auth.extra_attributes.should == {:full_name => 'Test', :address => 'Test'}
48
+ end
49
+
50
+ end
51
+ end
52
+
53
+
@@ -0,0 +1,149 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ $LOG = Logger.new(File.basename(__FILE__).gsub('.rb','.log'))
5
+
6
+ RSpec.configure do |config|
7
+ config.include Capybara
8
+ end
9
+
10
+ VALID_USERNAME = 'spec_user'
11
+ VALID_PASSWORD = 'spec_password'
12
+
13
+ ATTACK_USERNAME = '%3E%22%27%3E%3Cscript%3Ealert%2826%29%3C%2Fscript%3E&password=%3E%22%27%3E%3Cscript%3Ealert%2826%29%3C%2Fscript%3E&lt=%3E%22%27%3E%3Cscript%3Ealert%2826%29%3C%2Fscript%3E&service=%3E%22%27%3E%3Cscript%3Ealert%2826%29%3C%2Fscript%3E'
14
+ INVALID_PASSWORD = 'invalid_password'
15
+
16
+ describe 'CASServer' do
17
+
18
+ before do
19
+ @target_service = 'http://my.app.test'
20
+ end
21
+
22
+ describe "/login" do
23
+ before do
24
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
25
+ reset_spec_database
26
+ end
27
+
28
+ it "logs in successfully with valid username and password without a target service" do
29
+ visit "/login"
30
+
31
+ fill_in 'username', :with => VALID_USERNAME
32
+ fill_in 'password', :with => VALID_PASSWORD
33
+ click_button 'login-submit'
34
+
35
+ page.should have_content("You have successfully logged in")
36
+ end
37
+
38
+ it "fails to log in with invalid password" do
39
+ visit "/login"
40
+ fill_in 'username', :with => VALID_USERNAME
41
+ fill_in 'password', :with => INVALID_PASSWORD
42
+ click_button 'login-submit'
43
+
44
+ page.should have_content("Incorrect username or password")
45
+ end
46
+
47
+ it "logs in successfully with valid username and password and redirects to target service" do
48
+ visit "/login?service="+CGI.escape(@target_service)
49
+
50
+ fill_in 'username', :with => VALID_USERNAME
51
+ fill_in 'password', :with => VALID_PASSWORD
52
+
53
+ click_button 'login-submit'
54
+
55
+ page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?\?ticket=ST\-[1-9rA-Z]+/
56
+ end
57
+
58
+ it "preserves target service after invalid login" do
59
+ visit "/login?service="+CGI.escape(@target_service)
60
+
61
+ fill_in 'username', :with => VALID_USERNAME
62
+ fill_in 'password', :with => INVALID_PASSWORD
63
+ click_button 'login-submit'
64
+
65
+ page.should have_content("Incorrect username or password")
66
+ page.should have_xpath('//input[@id="service"]', :value => @target_service)
67
+ end
68
+
69
+ it "uses appropriate localization when 'lang' prameter is given (make sure you've run `rake localization:mo` first!!)" do
70
+ visit "/login?lang=pl"
71
+ page.should have_content("Użytkownik")
72
+
73
+ visit "/login?lang=pt_BR"
74
+ page.should have_content("Usuário")
75
+
76
+ visit "/login?lang=en"
77
+ page.should have_content("Username")
78
+ end
79
+
80
+ it "is not vunerable to Cross Site Scripting" do
81
+ visit '/login?service=%22%2F%3E%3cscript%3ealert%2832%29%3c%2fscript%3e'
82
+ page.should_not have_content("alert(32)")
83
+ page.should_not have_xpath("//script")
84
+ #page.should have_xpath("<script>alert(32)</script>")
85
+ end
86
+
87
+ end # describe '/login'
88
+
89
+
90
+ describe '/logout' do
91
+
92
+ before do
93
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
94
+ reset_spec_database
95
+ end
96
+
97
+ it "logs out successfully" do
98
+ visit "/logout"
99
+
100
+ page.should have_content("You have successfully logged out")
101
+ end
102
+
103
+ it "logs out successfully and redirects to target service" do
104
+ visit "/logout?gateway=true&service="+CGI.escape(@target_service)
105
+
106
+ page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?/
107
+ end
108
+
109
+ end # describe '/logout'
110
+
111
+ describe 'Configuration' do
112
+ it "uri_path value changes prefix of routes" do
113
+ load_server(File.dirname(__FILE__) + "/alt_config.yml")
114
+ @target_service = 'http://my.app.test'
115
+
116
+ visit "/test/login"
117
+ page.status_code.should_not == 404
118
+
119
+ visit "/test/logout"
120
+ page.status_code.should_not == 404
121
+ end
122
+ end
123
+
124
+ describe "proxyValidate" do
125
+ before do
126
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
127
+ reset_spec_database
128
+
129
+ visit "/login?service="+CGI.escape(@target_service)
130
+
131
+ fill_in 'username', :with => VALID_USERNAME
132
+ fill_in 'password', :with => VALID_PASSWORD
133
+
134
+ click_button 'login-submit'
135
+
136
+ page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?\?ticket=ST\-[1-9rA-Z]+/
137
+ @ticket = page.current_url.match(/ticket=(.*)$/)[1]
138
+ end
139
+
140
+ it "should have extra attributes in proper format" do
141
+ visit "/serviceValidate?service=#{CGI.escape(@target_service)}&ticket=#{@ticket}"
142
+
143
+ encoded_utf_string = "&#1070;&#1090;&#1092;" # actual string is "Ютф"
144
+ page.body.should match("<test_utf_string>#{encoded_utf_string}</test_utf_string>")
145
+ page.body.should match("<test_numeric>123.45</test_numeric>")
146
+ page.body.should match("<test_utf_string>&#1070;&#1090;&#1092;</test_utf_string>")
147
+ end
148
+ end
149
+ end