synapses-cas 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/CHANGELOG +3 -0
 - data/Gemfile +3 -0
 - data/LICENSE +27 -0
 - data/README.md +20 -0
 - data/Rakefile +2 -0
 - data/bin/synapses-cas +30 -0
 - data/config.ru +17 -0
 - data/config/config.example.yml +592 -0
 - data/config/unicorn.rb +88 -0
 - data/db/migrate/001_create_initial_structure.rb +47 -0
 - data/lib/casserver.rb +11 -0
 - data/lib/casserver/authenticators/active_directory_ldap.rb +19 -0
 - data/lib/casserver/authenticators/active_resource.rb +127 -0
 - data/lib/casserver/authenticators/authlogic_crypto_providers/aes256.rb +43 -0
 - data/lib/casserver/authenticators/authlogic_crypto_providers/bcrypt.rb +92 -0
 - data/lib/casserver/authenticators/authlogic_crypto_providers/md5.rb +34 -0
 - data/lib/casserver/authenticators/authlogic_crypto_providers/sha1.rb +59 -0
 - data/lib/casserver/authenticators/authlogic_crypto_providers/sha512.rb +50 -0
 - data/lib/casserver/authenticators/base.rb +67 -0
 - data/lib/casserver/authenticators/client_certificate.rb +47 -0
 - data/lib/casserver/authenticators/google.rb +58 -0
 - data/lib/casserver/authenticators/ldap.rb +147 -0
 - data/lib/casserver/authenticators/ntlm.rb +88 -0
 - data/lib/casserver/authenticators/open_id.rb +22 -0
 - data/lib/casserver/authenticators/sql.rb +133 -0
 - data/lib/casserver/authenticators/sql_authlogic.rb +93 -0
 - data/lib/casserver/authenticators/sql_encrypted.rb +75 -0
 - data/lib/casserver/authenticators/sql_md5.rb +19 -0
 - data/lib/casserver/authenticators/sql_rest_auth.rb +82 -0
 - data/lib/casserver/authenticators/test.rb +22 -0
 - data/lib/casserver/cas.rb +323 -0
 - data/lib/casserver/localization.rb +13 -0
 - data/lib/casserver/model.rb +270 -0
 - data/lib/casserver/server.rb +758 -0
 - data/lib/casserver/utils.rb +32 -0
 - data/lib/casserver/views/_login_form.erb +42 -0
 - data/lib/casserver/views/layout.erb +18 -0
 - data/lib/casserver/views/login.erb +30 -0
 - data/lib/casserver/views/proxy.builder +12 -0
 - data/lib/casserver/views/proxy_validate.builder +25 -0
 - data/lib/casserver/views/service_validate.builder +18 -0
 - data/lib/casserver/views/validate.erb +2 -0
 - data/locales/de.yml +27 -0
 - data/locales/en.yml +26 -0
 - data/locales/es.yml +26 -0
 - data/locales/es_ar.yml +26 -0
 - data/locales/fr.yml +26 -0
 - data/locales/jp.yml +26 -0
 - data/locales/pl.yml +26 -0
 - data/locales/pt.yml +26 -0
 - data/locales/ru.yml +26 -0
 - data/locales/zh.yml +26 -0
 - data/locales/zh_tw.yml +26 -0
 - data/public/themes/cas.css +126 -0
 - data/public/themes/notice.png +0 -0
 - data/public/themes/ok.png +0 -0
 - data/public/themes/simple/bg.png +0 -0
 - data/public/themes/simple/favicon.png +0 -0
 - data/public/themes/simple/login_box_bg.png +0 -0
 - data/public/themes/simple/logo.png +0 -0
 - data/public/themes/simple/theme.css +28 -0
 - data/public/themes/urbacon/bg.png +0 -0
 - data/public/themes/urbacon/login_box_bg.png +0 -0
 - data/public/themes/urbacon/logo.png +0 -0
 - data/public/themes/urbacon/theme.css +33 -0
 - data/public/themes/warning.png +0 -0
 - data/resources/init.d.sh +58 -0
 - data/setup.rb +1585 -0
 - data/spec/alt_config.yml +50 -0
 - data/spec/authenticators/active_resource_spec.rb +109 -0
 - data/spec/authenticators/ldap_spec.rb +53 -0
 - data/spec/casserver_spec.rb +156 -0
 - data/spec/default_config.yml +50 -0
 - data/spec/model_spec.rb +42 -0
 - data/spec/spec.opts +4 -0
 - data/spec/spec_helper.rb +89 -0
 - data/spec/utils_spec.rb +53 -0
 - data/tasks/bundler.rake +4 -0
 - data/tasks/db/migrate.rake +12 -0
 - data/tasks/spec.rake +10 -0
 - metadata +380 -0
 
    
        data/spec/alt_config.yml
    ADDED
    
    | 
         @@ -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,156 @@ 
     | 
|
| 
      
 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::DSL
         
     | 
| 
      
 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<=%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 based on Accept-Language header" do
         
     | 
| 
      
 70 
     | 
    
         
            +
                  
         
     | 
| 
      
 71 
     | 
    
         
            +
                  page.driver.options[:headers] = {'HTTP_ACCEPT_LANGUAGE' => 'pl'}
         
     | 
| 
      
 72 
     | 
    
         
            +
                  #visit "/login?lang=pl"
         
     | 
| 
      
 73 
     | 
    
         
            +
                  visit "/login"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  page.should have_content("Użytkownik")
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  page.driver.options[:headers] = {'HTTP_ACCEPT_LANGUAGE' => 'pt_BR'}
         
     | 
| 
      
 77 
     | 
    
         
            +
                  #visit "/login?lang=pt_BR"
         
     | 
| 
      
 78 
     | 
    
         
            +
                  visit "/login"
         
     | 
| 
      
 79 
     | 
    
         
            +
                  page.should have_content("Usuário")
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  page.driver.options[:headers] = {'HTTP_ACCEPT_LANGUAGE' => 'en'}
         
     | 
| 
      
 82 
     | 
    
         
            +
                  #visit "/login?lang=en"
         
     | 
| 
      
 83 
     | 
    
         
            +
                  visit "/login"
         
     | 
| 
      
 84 
     | 
    
         
            +
                  page.should have_content("Username")
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                it "is not vunerable to Cross Site Scripting" do
         
     | 
| 
      
 88 
     | 
    
         
            +
                  visit '/login?service=%22%2F%3E%3cscript%3ealert%2832%29%3c%2fscript%3e'
         
     | 
| 
      
 89 
     | 
    
         
            +
                  page.should_not have_content("alert(32)")
         
     | 
| 
      
 90 
     | 
    
         
            +
                  page.should_not have_xpath("//script")
         
     | 
| 
      
 91 
     | 
    
         
            +
                  #page.should have_xpath("<script>alert(32)</script>")
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
              end # describe '/login'
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              describe '/logout' do
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                before do
         
     | 
| 
      
 100 
     | 
    
         
            +
                  load_server(File.dirname(__FILE__) + "/default_config.yml")
         
     | 
| 
      
 101 
     | 
    
         
            +
                  reset_spec_database
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                it "logs out successfully" do
         
     | 
| 
      
 105 
     | 
    
         
            +
                  visit "/logout"
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                  page.should have_content("You have successfully logged out")
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                it "logs out successfully and redirects to target service" do
         
     | 
| 
      
 111 
     | 
    
         
            +
                  visit "/logout?gateway=true&service="+CGI.escape(@target_service)
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                  page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?/
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
              end # describe '/logout'
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
              describe 'Configuration' do
         
     | 
| 
      
 119 
     | 
    
         
            +
                it "uri_path value changes prefix of routes" do
         
     | 
| 
      
 120 
     | 
    
         
            +
                  load_server(File.dirname(__FILE__) + "/alt_config.yml")
         
     | 
| 
      
 121 
     | 
    
         
            +
                  @target_service = 'http://my.app.test'
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                  visit "/test/login"
         
     | 
| 
      
 124 
     | 
    
         
            +
                  page.status_code.should_not == 404
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                  visit "/test/logout"
         
     | 
| 
      
 127 
     | 
    
         
            +
                  page.status_code.should_not == 404
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
              describe "proxyValidate" do
         
     | 
| 
      
 132 
     | 
    
         
            +
                before do
         
     | 
| 
      
 133 
     | 
    
         
            +
                  load_server(File.dirname(__FILE__) + "/default_config.yml")
         
     | 
| 
      
 134 
     | 
    
         
            +
                  reset_spec_database
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  visit "/login?service="+CGI.escape(@target_service)
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                  fill_in 'username', :with => VALID_USERNAME
         
     | 
| 
      
 139 
     | 
    
         
            +
                  fill_in 'password', :with => VALID_PASSWORD
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  click_button 'login-submit'
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                  page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?\?ticket=ST\-[1-9rA-Z]+/
         
     | 
| 
      
 144 
     | 
    
         
            +
                  @ticket = page.current_url.match(/ticket=(.*)$/)[1]
         
     | 
| 
      
 145 
     | 
    
         
            +
                end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                it "should have extra attributes in proper format" do
         
     | 
| 
      
 148 
     | 
    
         
            +
                  visit "/serviceValidate?service=#{CGI.escape(@target_service)}&ticket=#{@ticket}"
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  encoded_utf_string = "Ютф" # actual string is "Ютф"
         
     | 
| 
      
 151 
     | 
    
         
            +
                  page.body.should match("<test_utf_string>#{encoded_utf_string}</test_utf_string>")
         
     | 
| 
      
 152 
     | 
    
         
            +
                  page.body.should match("<test_numeric>123.45</test_numeric>")
         
     | 
| 
      
 153 
     | 
    
         
            +
                  page.body.should match("<test_utf_string>Ютф</test_utf_string>")
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
              end
         
     | 
| 
      
 156 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,50 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            server: webrick
         
     | 
| 
      
 2 
     | 
    
         
            +
            port: 6543
         
     | 
| 
      
 3 
     | 
    
         
            +
            #ssl_cert: test.pem
         
     | 
| 
      
 4 
     | 
    
         
            +
            #uri_path: /cas
         
     | 
| 
      
 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
         
     | 
    
        data/spec/model_spec.rb
    ADDED
    
    | 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/spec_helper'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module CASServer
         
     | 
| 
      
 5 
     | 
    
         
            +
            end
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'casserver/model'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            describe CASServer::Model::LoginTicket, '.cleanup(max_lifetime, max_unconsumed_lifetime)' do
         
     | 
| 
      
 9 
     | 
    
         
            +
              let(:max_lifetime) { -1 }
         
     | 
| 
      
 10 
     | 
    
         
            +
              let(:max_unconsumed_lifetime) { -2 }
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              before do
         
     | 
| 
      
 13 
     | 
    
         
            +
                load_server(File.dirname(__FILE__) + "/default_config.yml")
         
     | 
| 
      
 14 
     | 
    
         
            +
                reset_spec_database
         
     | 
| 
      
 15 
     | 
    
         
            +
                
         
     | 
| 
      
 16 
     | 
    
         
            +
                CASServer::Model::LoginTicket.create :ticket => 'test', :client_hostname => 'test.local'
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              it 'should destroy all tickets created before the max lifetime' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                expect {
         
     | 
| 
      
 21 
     | 
    
         
            +
                  CASServer::Model::LoginTicket.cleanup(max_lifetime, max_unconsumed_lifetime)
         
     | 
| 
      
 22 
     | 
    
         
            +
                }.to change(CASServer::Model::LoginTicket, :count).by(-1)
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              it 'should destroy all unconsumed tickets not exceeding the max lifetime' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                expect {
         
     | 
| 
      
 27 
     | 
    
         
            +
                  CASServer::Model::LoginTicket.cleanup(max_lifetime, max_unconsumed_lifetime)
         
     | 
| 
      
 28 
     | 
    
         
            +
                }.to change(CASServer::Model::LoginTicket, :count).by(-1)
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            describe CASServer::Model::LoginTicket, '#to_s' do
         
     | 
| 
      
 33 
     | 
    
         
            +
              let(:ticket) { 'test' }
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              before do
         
     | 
| 
      
 36 
     | 
    
         
            +
                @login_ticket = CASServer::Model::LoginTicket.new :ticket => ticket
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              it 'should delegate #to_s to #ticket' do
         
     | 
| 
      
 40 
     | 
    
         
            +
                @login_ticket.to_s.should == ticket
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     |