├── .gitignore ├── .rspec ├── .simplecov ├── .travis.yml ├── Appraisals ├── CHANGELOG.txt ├── Gemfile ├── Guardfile ├── History.txt ├── LICENSE.txt ├── README.rdoc ├── Rakefile ├── TODO.md ├── VERSION ├── examples └── rails │ ├── README │ ├── app │ ├── controllers │ │ ├── advanced_example_controller.rb │ │ ├── application.rb │ │ └── simple_example_controller.rb │ └── views │ │ ├── advanced_example │ │ ├── index.html.erb │ │ └── my_account.html.erb │ │ └── simple_example │ │ └── index.html.erb │ ├── config │ ├── boot.rb │ ├── environment.rb │ ├── environments │ │ ├── development.rb │ │ ├── production.rb │ │ └── test.rb │ ├── initializers │ │ ├── inflections.rb │ │ ├── mime_types.rb │ │ └── new_rails_defaults.rb │ └── routes.rb │ ├── log │ ├── development.log │ ├── production.log │ ├── server.log │ └── test.log │ └── script │ ├── about │ ├── console │ └── server ├── gemfiles ├── .gitignore ├── rails23.gemfile ├── rails30.gemfile ├── rails31.gemfile └── rails32.gemfile ├── lib ├── casclient.rb ├── casclient │ ├── client.rb │ ├── frameworks │ │ └── rails │ │ │ ├── cas_proxy_callback_controller.rb │ │ │ └── filter.rb │ ├── responses.rb │ ├── tickets.rb │ └── tickets │ │ ├── storage.rb │ │ └── storage │ │ └── active_record_ticket_store.rb ├── rubycas-client.rb └── rubycas-client │ └── version.rb ├── rails_generators └── active_record_ticket_store │ ├── USAGE │ ├── active_record_ticket_store_generator.rb │ └── templates │ ├── README │ └── migration.rb ├── rubycas-client.gemspec └── spec ├── .gitignore ├── casclient ├── client_spec.rb ├── frameworks │ └── rails │ │ └── filter_spec.rb ├── tickets │ ├── storage │ │ └── active_record_ticket_store_spec.rb │ └── storage_spec.rb └── validation_response_spec.rb ├── database.yml ├── spec_helper.rb └── support ├── action_controller_helpers.rb ├── active_record_helpers.rb ├── local_hash_ticket_store.rb ├── local_hash_ticket_store_spec.rb └── shared_examples_for_ticket_stores.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.gem 3 | 4 | # simplecov generated 5 | coverage 6 | 7 | # rdoc generated 8 | rdoc 9 | 10 | # yard generated 11 | doc 12 | .yardoc 13 | 14 | # bundler 15 | .bundle 16 | 17 | # jeweler generated 18 | pkg 19 | 20 | # rbenv and rvm configs 21 | .rbenv-version 22 | .rbenv-vars 23 | .rvmrc 24 | .ruby-version 25 | 26 | tmp 27 | 28 | .project 29 | 30 | Gemfile.lock 31 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format nested 2 | --color 3 | -------------------------------------------------------------------------------- /.simplecov: -------------------------------------------------------------------------------- 1 | SimpleCov.start do 2 | add_filter "/spec/.*_spec\.rb" 3 | add_filter "/spec/.*/shared_examples.*" 4 | add_filter "/spec/.*/.*helper(s?).rb" 5 | end 6 | 7 | # vim: filetype=ruby 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | gemfile: 3 | - gemfiles/rails23.gemfile 4 | - gemfiles/rails30.gemfile 5 | - gemfiles/rails31.gemfile 6 | - gemfiles/rails32.gemfile 7 | rvm: 8 | - 1.8.7 9 | - 1.9.2 10 | - 1.9.3 11 | - 2.0.0 12 | - 2.1.0 13 | - jruby-18mode 14 | - jruby-19mode 15 | - rbx 16 | matrix: 17 | exclude: 18 | - rvm: 1.9.3 19 | gemfile: gemfiles/rails23.gemfile 20 | - rvm: 2.0.0 21 | gemfile: gemfiles/rails23.gemfile 22 | - rvm: 2.1.0 23 | gemfile: gemfiles/rails23.gemfile 24 | - rvm: jruby-19mode 25 | gemfile: gemfiles/rails23.gemfile 26 | - rvm: rbx 27 | gemfile: gemfiles/rails23.gemfile 28 | -------------------------------------------------------------------------------- /Appraisals: -------------------------------------------------------------------------------- 1 | appraise "rails23" do 2 | gem "activesupport", "~> 2.3.11" 3 | end 4 | 5 | appraise "rails30" do 6 | gem "rails", "~> 3.0.17" 7 | end 8 | 9 | appraise "rails31" do 10 | gem "rails", "~> 3.1.8" 11 | end 12 | 13 | appraise "rails32" do 14 | gem "rails", "~> 3.2.8" 15 | end 16 | 17 | # vim: filetype=ruby 18 | -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | See History.txt -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | gemspec 4 | 5 | group :tools do 6 | gem "guard" 7 | gem "guard-rspec" 8 | gem "guard-bundler" 9 | gem "fuubar" 10 | gem "rb-fsevent" 11 | gem "ruby_gntp", :group => :darwin 12 | end 13 | 14 | gem 'rubysl', :platform => :rbx 15 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | # A sample Guardfile 2 | # More info at https://github.com/guard/guard#readme 3 | 4 | guard 'bundler' do 5 | watch('Gemfile') 6 | # Uncomment next line if Gemfile contain `gemspec' command 7 | watch(/^.+\.gemspec/) 8 | end 9 | 10 | guard 'rspec', :version => 2, :cli => '-c -f Fuubar' do 11 | watch(%r{^spec/.+_spec\.rb$}) 12 | watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } 13 | watch('spec/spec_helper.rb') { "spec" } 14 | watch(%r{^spec/support/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } 15 | watch(%r{^spec/support/(.+)\.rb$}) { "spec" } 16 | end 17 | -------------------------------------------------------------------------------- /History.txt: -------------------------------------------------------------------------------- 1 | = RubyCAS-Client Changelog 2 | 3 | == Version 2.3.10.rc1 :: 2013-03-18 4 | 5 | * Bug Fixes 6 | * Fixed bug where ActiveRecordTicketStore failed to add the service 7 | ticket to the sessions table 8 | * Fixed compatibility of login_to_service with rubycas-server 1.1.x (@bradseefeld) 9 | * Fix an issue that prevented inspection of faked extra attributes on the filter (@yurikoval) 10 | * Fix travis builds running incorrectly (@tpicket66) 11 | * Remove dependency on rubycas-client-rails when Rails 3.x is being used (@KrisSiegel) 12 | * Fix an issue where the Ticket Store might break under Rails 3.x 13 | * Fix loading the ActiveRecordTicketStore by symbol 14 | 15 | * Other 16 | * Vastly expand combinations of ruby and rails versions that are considered supported. - see .travis.yml 17 | 18 | == Version 2.3.9 :: 2012-06-20 19 | 20 | * Other 21 | * ci against lots more ruby versions - see .travis.yml and the travis 22 | status page 23 | 24 | == Version 2.3.9rc1 :: 2012-03-24 25 | 26 | * Bug Fixes 27 | * Fixed issue that caused Single Sign Out to fail (@bryanlarsen and @soorajb) 28 | * Fixed issue in Filter#unauthorized! (@mscottford) 29 | * Fixed #38, boolean values are now preserved in extra attribute yaml 30 | parsing 31 | 32 | * New functionality 33 | * Tweak the CasProxyCallbackController so it can be used with 34 | rubycas-client-rails in Rails 3 (@bryanlarsen) 35 | * Add support for calling the CAS Server through an HTTP proxy (@shevaun) 36 | * Add support for specifying the service url to be added to the 37 | logout url (@dyson) 38 | * add support for extra attributes as xml attributes (@bhenderson) 39 | * Add :raw mode to extra attribute parsing 40 | 41 | * Other 42 | * Made writing and running rspec tests much easier 43 | * Added tests for Ticket Stores 44 | * Official support for jruby 1.6 45 | 46 | == Version 2.3.8 :: 2011-12-19 47 | 48 | * Bug Fixes 49 | * Fix some undesired behavior when parsing extra attributes as JSON 50 | * Simple attributes (that aren't JSON Objects) stay strings 51 | * We don't fallback to the YAML parser if JSON parsing fails 52 | 53 | == Version 2.3.7 :: 2011-11-29 54 | 55 | * Bug Fixes 56 | * Fixed bug in how service_urls with query parameters are handled 57 | * Fixed issue with setting correct temp directory under Rails 3.1 58 | 59 | == Version 2.3.6 :: 2011-11-22 60 | 61 | * Bug Fixes 62 | * Don't attempt to store single sign out information if sessions 63 | aren't enabled for this request. Fixes a problem were we were 64 | blowing up trying to modify a frozen session 65 | 66 | == Version 2.3.5 :: 2011-11-17 67 | 68 | * Bug Fixes 69 | * read_service_url will no longer include POST parameters on the 70 | service url 71 | 72 | == Version 2.3.3 :: 2011-11-11 73 | 74 | * Bug Fixes 75 | * Removed a puts that didn't get cleaned up 76 | * Fix a bug with parsing extra attributes caused by a strange edge 77 | case in active_support 78 | 79 | == Version 2.3.1 :: 2011-10-22 80 | 81 | * New Functionality 82 | * Add configuration option to expect complex extra attributes to be encoded 83 | in json instead of yaml 84 | * Split out storage mechanism for single sign out and proxy ticket storage so 85 | that it is modular 86 | 87 | * Changes to existing functionality 88 | * Change gem building from hoe to jeweler 89 | * expect extra attributes to be nested under a cas:attributes elemenet to 90 | improve compatibility with other extra attribute implementations 91 | * Unauthorized requests to URLs ending in .json now show an JSON formatted 92 | response 93 | 94 | * Bug Fixes 95 | * Fixed bug introduced by upstream patch that broke proxy ticket validation 96 | when using extra attributes 97 | * Fixed bug where extra attributes key was set on the session with a null 98 | value when faking with no extra attributes 99 | 100 | == Version 2.2.1 :: 2010-06-24 101 | 102 | * Removed a 3rd party patch to the logging mechanism that broke the client under 103 | some circumstances. Ouch. 2.2.0 should never have made it through QA. 104 | 105 | == Version 2.2.0 :: 2010-06-22 106 | 107 | RubyCAS-Client is now licensed under the MIT License. 108 | See http://www.opensource.org/licenses/mit-license.php 109 | 110 | * New functionality: 111 | * Added config parameter force_ssl_verification (self explanatory) [Roberto Klein] 112 | * Added explicit SingleSigoutFilter for Rails (convenient?) [Adam Elliot] 113 | * Added support for faking out the filter; useful when testing. See 114 | http://github.com/gunark/rubycas-client/commit/1eb10cc285d59193eede3d4406f95cad9db9d93a 115 | [Brian Hogan] 116 | 117 | * Changes to existing functionality: 118 | * Unauthorized requests to URLs ending in .xml now show an XML formatted 119 | response (#{failure_message}) [Roberto Klein] 120 | * Accepts HTTPFound (302) as a successful response from the CAS server (in 121 | addition to HTTPSuccess (2xx) [taryneast] 122 | 123 | * Bug fixes: 124 | * Got rid of warnings if @valid is not initialized in Responses [jamesarosen] 125 | * Fixed warning when setting the logger [jamesarosen] 126 | * Client should no longer crap out when using CAS v1 and extra_attributes is 127 | empty [jorahood] 128 | 129 | 130 | == Version 2.1.0 :: 2009-08-18 131 | 132 | * New functionality: 133 | * Added an adapter for the Merb framework. Thanks to Andrew O'Brien and 134 | Antono Vasiljev. 135 | * Implemented single-sign-out functionality. The client will now intercept 136 | single-sign-out requests and deal with them appropriately if the 137 | :enable_single_sign_out config option is set to true. This is currently 138 | disabled by default. (Currently this is only implemented for the Rails 139 | adapter) 140 | * Added logout method to Rails adapter to simplify the logout process. The 141 | logout method resets the local Rails session and redirects to the CAS 142 | logout page. 143 | * Added login_url method to the Rails filter. This will return the login 144 | URL for the current controller; useful when you want to show a "Login" 145 | link in a gatewayed page for an unauthenticated user. 146 | * Added cas_server_is_up? method to the client, as requested in issue #5. 147 | * Extra user attributes are now automatically unserialized if the incoming data 148 | is in YAML format. 149 | 150 | * Changes to existing functionality: 151 | * The 'service' parameter in the logout method has been renamed to 152 | 'destination' to better match the behaviour of other CAS clients. So for 153 | example, when you call logout_url("http://foo.example"), the method will 154 | now return "https://cas.example?destination=https%3A%2F%2Ffoo.example" 155 | instead of the old "https://cas.example?service=https%3A%2F%2Ffoo.example". 156 | RubyCAS-Server has been modified to deal with this as of version 0.6.0. 157 | * We now accept HTTP responses from the CAS server with status code 422 since 158 | RubyCAS-Server 0.7.0+ generates these in response to requests that are 159 | processable but contain invalid CAS data (for example an invalid service 160 | ticket). 161 | * Some behind-the-scenes changes to the way previous authentication info is 162 | reused by the Rails filter in subsequent requests (see the note below 163 | in the 2.0.1 release). From the user's and integrator's point of view 164 | there shouldn't be any obvious difference from 2.0.1. 165 | * Redirection loop interception: The client now logs a warning message when it 166 | believes that it is stuck in a redirection loop with the CAS server. If more 167 | than three of these redirects occur within one second, the client will 168 | redirect back to the login page with renew=1, forcing the user to try 169 | authenticating again. 170 | * Somewhat better handling and logging of errors resulting from CAS server 171 | connection/response problems. 172 | 173 | * Bug Fixes: 174 | * Fixed bug where the the service/destination parameter in the logout url 175 | would sometimes retain the 'ticket' value. The ticket is now automatically 176 | stripped from the logout url. 177 | * The client will no longer attempt to retrieve a PGT for an IOU that had 178 | already been previously retrieved. [yipdw1] 179 | 180 | * Misc: 181 | * Added complete CAS client integration examples for Rails and Merb 182 | applications under /examples. 183 | 184 | == Version 2.0.1 :: 2008-02-27 185 | 186 | * The Rails filter no longer by default redirects to the CAS server on 187 | every request. This restores the behaviour of RubyCAS-Client 1.x. 188 | In other words, if a session[:cas_user] value exists, the filter 189 | will assume that the user is authenticated without going through the 190 | CAS server. This behaviour can be disabled (so that a CAS re-check is 191 | done on every request) by setting the 'authenticate_on_every_request' 192 | option to true. See the "Re-authenticating on every request" section 193 | in the README.txt for details. 194 | 195 | == Version 2.0.0 :: 2008-02-14 196 | 197 | * COMPLETE RE-WRITE OF THE ENTIRE CLIENT FROM THE GROUND UP. Oh yes. 198 | * Core client has been abstracted out of the Rails adapter. It should now 199 | be possible to use the client in other frameworks (e.g. Camping). 200 | * Configuration syntax has completely changed. In other words, your old 201 | rubycas-client-1.x configuration will no longer work. See the README 202 | for details. 203 | * Added support for reading extra attributes from the CAS response (i.e. in 204 | addition to just the username). However currently this is somewhat useless 205 | since RubyCAS-Server does not yet provide a method for adding extra 206 | attributes to the responses it generates. 207 | 208 | ------------------------------------------------------------------------------ 209 | 210 | == Version 1.1.0 :: 2007-12-21 211 | 212 | * Fixed serious bug having to do with logouts. You can now end the 213 | CAS session on the client-side (i.e. force the client to re-authenticate) 214 | by setting session[:casfilteruser] = nil. 215 | * Added new GatewayFilter. This is identical to the normal Filter but 216 | has the gateway option set to true by default. This should make 217 | using the gateway option easier. 218 | * The CAS::Filter methods are now properly documented. 219 | * Simplified guess_service produces better URLs when redirecting to the CAS 220 | server for authentication and the service URL is not explicitly specified. 221 | [delagoya] 222 | * The correct method for overriding the service URL for the client is now 223 | properly documented. You should use service_url=, as server_name= no longer 224 | works and instead generates a warning message. 225 | * logout_url() now takes an additional 'service' parameter. If specified, this 226 | URL will be passed on to the CAS server as part of the logout URL. 227 | 228 | == Version 1.0.0 :: 2007-07-26 229 | 230 | * RubyCAS-Client has matured to the point where it is probably safe to 231 | take it out of beta and release version 1.0. 232 | * Non-SSL CAS URLs will now work. This may be useful for demo purposes, 233 | but certainly shouldn't be used in production. The client automatically 234 | disables SSL if the CAS URL starts with http (rather than https). [rubywmq] 235 | 236 | == Version 0.12.0 237 | 238 | * Prior to redirecting to the CAS login page, the client now stores the 239 | current service URI in a session variable. This value is used to 240 | validate the service ticket after the user comes back from the CAS 241 | server's login page. This should address issues where redirection 242 | from the CAS server resulted in a slightly different URI from the original 243 | one used prior to login redirection (for example due to variations in the 244 | way routing rules are applied by the server). 245 | * The client now handles malformed CAS server responses more gracefully. 246 | This makes debugging a malfunctioning CAS server somewhat easier. 247 | * When receiving a proxy-granting ticket, the cas_proxy_callback_controller 248 | can now take a parameter called 'pgt' (which is what ought to be used 249 | according to the published CAS spec) or 'pgtId' (which is what the JA-SIG 250 | CAS server uses). 251 | * Logging has been somewhat quieted down. Many messages that were previously 252 | logged as INFO are now logged as DEBUG. 253 | 254 | == Version 0.11.0 255 | 256 | * Added this changelog to advise users of major changes to the library. 257 | * Large chunks of the library have been re-written. Beware of the possibility 258 | of new bugs (although the re-write was meant to fix a whole slew of existing 259 | bugs, so you're almost certainly better off upgrading). 260 | * service and targetService parameters in requests are now properly URI-encoded, 261 | so the filter should behave properly when your service has query parameters. 262 | Thanks sakazuki for pointing out the problem. 263 | * You can now force the CAS client to re-authenticate itself with the CAS server 264 | (i.e. override the authentication stored in the session) by providing a new 265 | service ticket in the URI. In other words, the client will authenticate with 266 | CAS if: a) you have a 'ticket' parameter in the URI, and there is currently no 267 | authentication info in the session, or b) you have a 'ticket' parameter in the 268 | URI and this ticket is different than the ticket that was used to authenticat 269 | the existing session. This is especially useful when you are using CAS proxying, 270 | since it allows you to force re-authentication in proxied applications (for 271 | example, when the user has logged out and a new user has logged in in the parent 272 | proxy-granting application). 273 | * If your service URI has a 'ticket' parameter, it will now be automatically 274 | removed when passing the service as a parameter in any CAS request. This is 275 | done because at least some CAS servers will happily accept a service URI with 276 | a 'ticket' parameter, which will result in a URI with multiple 'ticket' 277 | parameters once you are redirected back to CAS (and that in turn can result 278 | in an endless redirection loop). 279 | * Logging has been greatly improved, which should make debugging your CAS 280 | installation much easier. Look for the logs under log/cas_client_RAILS_ENV.log 281 | * When you install RubyCAS-Client as a Rails plugin, it will now by default 282 | use a custom logger. You can change this by explicitly setting your own 283 | logger in your environment.rb, or by modifying the plugin's init.rb. 284 | * CasProxyCallbackController no longer checks to make sure that the incoming 285 | request is secure. The check is impossible since the secure header is not 286 | passed on by at least some reverse proxies (like Pound), and if you are using 287 | the callback controller then you are almost certainly also using a reverse 288 | proxy. 289 | * Cleaned up and updated documentation, fixed some example code. 290 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Portions of RubyCAS-Client contributed by Matt Zukowski are copyright (c) 2009 Urbacon Ltd. 2 | Other portions are copyright of their respective authors. 3 | 4 | The MIT License 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the "Software"), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | -------------------------------------------------------------------------------- /README.rdoc: -------------------------------------------------------------------------------- 1 | = In Need of New Maintainer 2 | 3 | Unfortunately, those of us who have been maintaining this project no longer have time to give it the attention it needs. If you are interested in taking over maintainence of it, please let us know! 4 | 5 | Otherwise, we recommend you consider one of the following alternatives: 6 | 7 | {rack-cas}[https://github.com/biola/rack-cas] 8 | 9 | {omniauth-cas}[https://github.com/dlindahl/omniauth-cas] 10 | 11 | {Build Status}[http://travis-ci.org/rubycas/rubycas-client] 12 | {}[https://codeclimate.com/github/rubycas/rubycas-client] 13 | 14 | = RubyCAS-Client 15 | 16 | Authors:: Matt Zukowski and Matt Campbell ; inspired by code by Ola Bini and Matt Walker 17 | Copyright:: Portions contributed by Matt Zukowski are copyright (c) 2009 Urbacon Ltd. 18 | Portions contributed by Matt Campbell, Rich Yarger and Rahul Joshi are copyright (c) 2011 Vibes Media LLC. 19 | Other portions are copyright of their respective authors. 20 | License:: MIT License 21 | Websites:: http://github.com/rubycas/rubycas-client 22 | http://github.com/rubycas/rubycas-client/wiki 23 | http://rubydoc.info/github/rubycas/rubycas-client/master/frames 24 | 25 | === RubyCAS-Client is a Ruby client library for Yale's Central Authentication Service (CAS) protocol. 26 | 27 | CAS provides a secure single sign on solution for web-based applications. The user logs in to your 28 | organization's CAS server, and is automatically authenticated for all other CAS-enabled applications. 29 | 30 | For general information about the open CAS protocol, please have a look at http://www.ja-sig.org/products/cas. 31 | 32 | If your organization does not already have a CAS server, you may be interested in RubyCAS-Client's sister project, 33 | RubyCAS-Server[http://code.google.com/p/rubycas-server/]. 34 | 35 | The RubyCAS-Client package includes adapters for Rails and Merb, although the client library itself can be 36 | adapted for other frameworks (for example an implementation for Camping is available via the Picnic[http://github.com/zuk/picnic/tree/master] 37 | library). 38 | 39 | 40 | == Getting help and reporting problems 41 | 42 | If you need help, try posting to the RubyCAS discussion group at http://groups.google.com/group/rubycas-server. 43 | 44 | To report problems, please use the Google Code issue tracker at http://code.google.com/p/rubycas-client/issues/list. 45 | 46 | API documentation (i.e. the RDocs) are available at http://rubycas-client.rubyforge.org 47 | 48 | 49 | == Installation 50 | 51 | The current version of RubyCAS-Client should work with Rails 2.3.6 and up. For compatibility with 52 | older Rails try using an older version of the client. 53 | 54 | You can download the latest version of RubyCAS-Client from the project's rubyforge page at 55 | http://rubyforge.org/projects/rubycas-client. 56 | 57 | However, if you're using Rails, it's easier to install the CAS client as a plugin: 58 | 59 | cd 60 | ./script/plugin install git://github.com/rubycas/rubycas-client.git 61 | 62 | Alternatively, the library is also installable as a RubyGem[http://rubygems.org]: 63 | 64 | gem install rubycas-client 65 | 66 | If your Rails application is under Subversion control, you can also install the plugin as an svn:external, ensuring that 67 | you always have the latest bleeding-edge version of RubyCAS-Client: 68 | 69 | ./script/plugin install -x http://svn.github.com/rubycas/rubycas-client.git 70 | 71 | 72 | == Usage Examples 73 | 74 | If you'd rather jump right in, have a look at the example Rails and Merb applications pre-configured for CAS 75 | authentication: 76 | 77 | http://github.com/rubycas/rubycas-client/tree/master/examples 78 | 79 | 80 | Otherwise, continue reading for a step-by-step guide for integrating RubyCAS-Client with Rails: 81 | 82 | 83 | ==== Using RubyCAS-Client in Rails controllers 84 | 85 | Note that from this point on we are assuming that you have a working CAS server up and running! 86 | 87 | After installing RubyCAS-Client as a plugin (see above), add the following to your app's config/environment.rb 88 | (make sure that you put it at the bottom of the file, *after* the Rails Initializer): 89 | 90 | CASClient::Frameworks::Rails::Filter.configure( 91 | :cas_base_url => "https://cas.example.foo/" 92 | ) 93 | 94 | (Change the :cas_base_url value to your CAS server's base URL; also note that many CAS servers are configured 95 | with a base URL that looks more like "https://cas.example.foo/cas".) 96 | 97 | Then, in your app/controllers/application.rb (or in whichever controller you want to add the CAS filter for): 98 | 99 | before_filter CASClient::Frameworks::Rails::Filter 100 | 101 | That's it. You should now find that you are redirected to your CAS login page whenever you try to access any action 102 | in your protected controller. You can of course qualify the before_filter as you would with any other ActionController 103 | filter. For example: 104 | 105 | before_filter CASClient::Frameworks::Rails::Filter, :except => [ :unprotected_action, :another_unprotected_action ] 106 | 107 | Once the user has been authenticated, their authenticated username is available under session[:cas_user], 108 | If you want to do something with this username (for example load a user record from the database), you can append another 109 | filter method that checks for this value and does whatever you need it to do. 110 | 111 | Note: If Rails complains about missing constants, try adding this before the CASClient configuration: 112 | 113 | require 'casclient' 114 | require 'casclient/frameworks/rails/filter' 115 | 116 | 117 | ==== A more complicated example 118 | 119 | Here is a more complicated configuration showing most of the configuration options along with their default values 120 | (this does not show proxy options, which are covered in the next section): 121 | 122 | # enable detailed CAS logging 123 | cas_logger = CASClient::Logger.new(::Rails.root+'/log/cas.log') 124 | cas_logger.level = Logger::DEBUG 125 | 126 | CASClient::Frameworks::Rails::Filter.configure( 127 | :cas_base_url => "https://cas.example.foo/", 128 | :login_url => "https://cas.example.foo/login", 129 | :logout_url => "https://cas.example.foo/logout", 130 | :validate_url => "https://cas.example.foo/proxyValidate", 131 | :username_session_key => :cas_user, 132 | :extra_attributes_session_key => :cas_extra_attributes, 133 | :logger => cas_logger, 134 | :enable_single_sign_out => true, 135 | :service_url => "https://mysite.service.com" 136 | ) 137 | 138 | Note that normally it is not necessary to specify :login_url, :logout_url, and :validate_url. 139 | These values are automatically set to standard CAS defaults based on the given :cas_base_url. 140 | 141 | The :username_session_key value determines the key under which you can find the CAS username in the Rails session hash. 142 | 143 | Any additional info that the CAS server might have supplied about the user during authentication will be found under the 144 | :extra_attributes_session_key value in the Rails session hash (i.e. given the above configuration, you would find this 145 | info under session[:cas_extra_attributes]). 146 | 147 | An arbitrary Logger instance can be given as the :logger parameter. In the example above we log all CAS activity to a 148 | log/cas.log file in your Rails app's directory. 149 | 150 | The service url sets the service parameter that will be sent to CAS for every authentication. This can be useful if you are 151 | implementing the single logout feature (supported by some CAS Servers) or would like to funnel all authentications through a specific action. 152 | 153 | ==== Re-authenticating on every request (i.e. the "single sign-out problem") 154 | 155 | By default, the Rails filter will only authenticate with the CAS server when no session[:cas_user] value exists. Once the user 156 | has been authenticated, no further CAS forwarding is done until the user's session is wiped. This saves you 157 | the trouble of having to do this check yourself (since in most cases it is not advisable to go through the CAS server 158 | on every request -- this is slow and would potentially lead to problems, for example for AJAX requests). However, 159 | the disadvantage is that the filter no longer checks to make sure that the user's CAS session is still actually open. 160 | In other words it is possible for the user's authentication session to be closed on the CAS server without the 161 | client application knowing about it. 162 | 163 | To address this, RubyCAS-Client now supports the new "Single Sign-Out" functionality in CAS 3.1, allowing the server to 164 | notify the client application that the CAS session is closed. The client will automatically intercept Single Sign-Out 165 | requsts from the CAS server, but in order for this to work you must configure your Rails application as follows: 166 | 167 | 1. The Rails session store must be set to ActiveRecord: config.action_controller.session_store = :active_record_store 168 | 2. The server must be able to read and write to Rails.root/tmp/sessions. If you are in a clustered environment, 169 | the contents of this directory must be shared between all server instances. 170 | 3. Cross-site request forgery protection must be disabled. In your application.rb: self.allow_forgery_protection = false. 171 | (Or rather you may want to disable forgery protection only for actions that are behind the CAS filter.) 172 | 4. Finally, you must add :enable_single_sign_out => true to your CAS client config (a similar option must be 173 | enabled on the CAS server, if you're using RubyCAS-Server). 174 | 175 | The best way to debug single-sign out functionality is to configure your CAS client with logging (see above) and then watch the 176 | log to ensure that single-sign out requests from the server are being processed correctly. 177 | 178 | 179 | Alternatively, it is possible to disable authentication persistence in the client by setting the :authenticate_on_every_request 180 | configuration option to true as, in the example in the previous section. However, this is not recommended as it will almost 181 | certainly have a deleterious impact on performance and can interfere with certain HTTP transactions (AJAX requests, for example). 182 | 183 | 184 | ==== Defining a 'logout' action 185 | 186 | Your Rails application's controller(s) will probably have some sort of logout function. Here you can do any necessary local 187 | cleanup, and then call CASClient::Frameworks::Rails::Filter.logout(controller). For example: 188 | 189 | class ApplicationController < ActionController::Base 190 | 191 | # ... 192 | 193 | def logout 194 | # optionally do some local cleanup here 195 | # ... 196 | 197 | CASClient::Frameworks::Rails::Filter.logout(self) 198 | end 199 | end 200 | 201 | By default, the logout method will clear the local Rails session, do some local CAS cleanup, and redirect to the CAS 202 | logout page. Additionally, the request.referer value from the controller instance is passed to the 203 | CAS server as a 'destination' parameter. This allows RubyCAS server to provide a follow-up login page allowing 204 | the user to log back in to the service they just logged out from using a different username and password. Other 205 | CAS server implemenations may use this 'destination' parameter in different ways. 206 | 207 | ==== Gatewayed (i.e. optional) authentication 208 | 209 | "Gatewaying" essentially allows for optional CAS authentication. Users who already have a pre-existing CAS SSO session 210 | will be automatically authenticated for the gatewayed service, while those who do not will be allowed to access the service 211 | without authentication. This is useful for example when you want to show some additional private content on a homepage to 212 | authenticated users, but also want anonymous users to be able to access the page without first logging in. 213 | 214 | To allow users to access a page without authenticatin, simply use CASClient::Frameworks::Rails::GatewayFilter 215 | in place of CASClient::Frameworks::Rails::Filter in your controller. For example, you may want to require 216 | CAS authentication for all actions in a controller except the index action: 217 | 218 | class ExampleController < ApplicationController 219 | before_filter CASClient::Frameworks::Rails::GatewayFilter, :only => :index 220 | before_filter CASClient::Frameworks::Rails::Filter, :except => :index 221 | 222 | # ... 223 | end 224 | 225 | To provide a login URL for unauthenticated users: 226 | 227 | <%= link_to("Login", CASClient::Frameworks::Rails::Filter.login_url(controller)) %> 228 | 229 | ==== How to act as a CAS proxy 230 | 231 | CAS 2.0 has a built-in mechanism that allows a CAS-authenticated application to pass on its authentication to other applications. 232 | An example where this is useful might be a portal site, where the user logs in to a central website and then gets forwarded to 233 | various other sites that run independently of the portal system (but are always accessed via the portal). The exact mechanism 234 | behind this is rather complicated so I won't go over it here. If you wish to learn more about CAS proxying, a great walkthrough 235 | is available at http://www.ja-sig.org/wiki/display/CAS/Proxy+CAS+Walkthrough. 236 | 237 | RubyCAS-Client fully supports proxying, so a CAS-protected Rails application can act as a CAS proxy. 238 | 239 | Additionally, RubyCAS-Client comes with a controller that can act as a CAS proxy callback receiver. This is necessary because 240 | when your application requests to act as a CAS proxy, the CAS server must contact your application to deposit the proxy-granting-ticket 241 | (PGT). Note that in this case the CAS server CONTACTS YOU, rather than you contacting the CAS server (as in all other CAS operations). 242 | 243 | Confused? Don't worry, you don't really have to understand this to use it. To enable your Rails app to act as a CAS proxy, 244 | all you need to do is this: 245 | 246 | In your config/environment.rb: 247 | 248 | # enable detailed CAS logging for easier troubleshooting 249 | cas_logger = CASClient::Logger.new(::Rails.root+'/log/cas.log') 250 | cas_logger.level = Logger::DEBUG 251 | 252 | CASClient::Frameworks::Rails::Filter.configure( 253 | :cas_base_url => "https://cas.example.foo/", 254 | :proxy_callback_url => "https://cas-proxy-callback.example.foo/cas_proxy_callback/receive_pgt", 255 | :logger => cas_logger 256 | ) 257 | 258 | In config/routes.rb make sure that you have a route that will allow requests to /cas_proxy_callback/:action to be routed to the 259 | CasProxyCallbackController. This should work as-is with the standard Rails routes setup, but if you have disabled the default 260 | route, you should add the following: 261 | 262 | map.cas_proxy_callback 'cas_proxy_callback/:action', :controller => 'cas_proxy_callback' 263 | 264 | Now here's a big giant caveat: your CAS callback application and your CAS proxy application must run on separate Rails servers. 265 | In other words, if you want a Rails app to act as a CAS ticket-granting proxy, the cas_proxy_callback controller 266 | must run on a different server. This is because Rails does not properly support handling of concurrent requests. The CAS proxy mechanism 267 | acts in such a way that if your proxy application and your callback controller were on the same server 268 | you would end up with a deadlock (the CAS server would be waiting for its callback to be accepted by your Rails server, 269 | but your Rails server wouldn't respond to the CAS server's callback until the CAS server responded back first). 270 | 271 | The simplest workaround is this: 272 | 273 | Run rails using a server that handles multiple concurrent requests. In development, you can use Phusion Passenger Standalone, 274 | POW (http://pow.cx/), unicorn and many others. In production, I imagine you already support multiple concurrent requests. 275 | 276 | That's it. The proxy_callback_controller doesn't require any additional configuration. It doesn't access the database 277 | or anything of that sort. 278 | 279 | Once your user logs in to CAS via your application, you can do the following to obtain a service ticket that can then be used 280 | to authenticate another application: 281 | 282 | service_uri = "http://some-other-application.example.foo" 283 | proxy_granting_ticket = session[:cas_pgt] 284 | proxy_ticket = CASClient::Frameworks::Rails::Filter.client.request_proxy_ticket(proxy_granting_ticket, service_uri) 285 | 286 | proxy_ticket should now contain a valid proxy ticket. You can use it to authenticate other services by sending it together with 287 | the service URI as parameters to your target application: 288 | 289 | http://some-other-application.example.foo?service=#{CGI::escape(proxy_ticket.service)}&ticket=#{proxy_ticket.ticket} 290 | 291 | This is of course assuming that http://some-other-application.example.foo is also protected by the CAS filter. 292 | Note that you should always URI-encode your service parameter inside URIs! 293 | 294 | Note that #request_proxy_ticket returns a CASClient::ProxyTicket object, which is why we need to call #ticket on it 295 | to retrieve the actual service ticket string. 296 | 297 | ===== Additional proxying notes and caveats 298 | 299 | The proxy url must be an https address. Otherwise CAS will refuse to communicate with it. This means that if you are using 300 | the bundled cas_proxy_callback controller, you will have to host your application on an https-enabled server. This can be a bit 301 | tricky with Rails. WEBrick's SSL support is difficult to configure, and Mongrel doesn't support SSL at all. One workaround is to 302 | use a reverse proxy like Pound[http://www.apsis.ch/pound/], which will accept https connections and locally re-route them 303 | to your Rails application. Also, note that self-signed SSL certificates likely won't work. You will probably need to use 304 | a real certificate purchased from a trusted CA authority (there are ways around this, but good luck :) 305 | 306 | 307 | == SSL Support 308 | 309 | Make sure you have the Ruby OpenSSL library installed. Otherwise you may get errors like: 310 | 311 | no such file to load -- net/https 312 | 313 | To install the library on an Debian/Ubuntu system: 314 | 315 | sudo apt-get install libopenssl-ruby 316 | 317 | For other platforms you'll have to figure it out yourself. 318 | 319 | == Testing 320 | 321 | In some cases, especially those using Cucumber or other tools that simply can't work with 322 | CAS, it may be necessary to work around CAS instead. 323 | 324 | In your test or Cucumber step definition, simply fake out CAS. 325 | 326 | CASClient::Frameworks::Rails::Filter.fake("homer") 327 | 328 | This functionality was present in the original version of this plugin. 329 | The value of the username is stored in session[:cas_user] (or the user specified field) and session[:casfilteruser] for backwards-compatibility. 330 | 331 | If you need to fake out extra attributes, you can do so like this: 332 | 333 | CASClient::Frameworks::Rails::Filter.fake("homer", {:role => "user", :email => "homer@test.foo"}) 334 | 335 | And the extra attributes will get put in the proper place in the session. 336 | 337 | == License 338 | 339 | RubyCAS-Client is licensed for use under the terms of the MIT License. 340 | See the LICENSE.txt file bundled with the official RubyCAS-Client distribution for details. 341 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | require 'bundler/setup' 3 | require 'rake' 4 | require 'bundler/gem_tasks' 5 | 6 | require 'appraisal' 7 | 8 | require 'rspec/core/rake_task' 9 | RSpec::Core::RakeTask.new 10 | 11 | task :default => [:spec] 12 | 13 | namespace :spec do 14 | desc 'run the specs and features against every gemset.' 15 | task :all do 16 | system("bundle exec rake -s appraisal spec ;") 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # Planned Changes 2 | 3 | Also take a look at the [issues page](/rubycas/rubycas-client/issues) 4 | 5 | ## Version 2.4 6 | 7 | 1. Support for Ruby 1.9.3 8 | 1. Integration with travis for CI 9 | 1. Test against Rails 2.3 10 | 1. Test without Rails 11 | 1. Test against 1.8.7, 1.9.2, 1.9.3, jruby 12 | 13 | ## Version 3.0 14 | 15 | 1. Convert test cases from riot to rspec2 - Done! 16 | 1. Move Service Callback, PGT Callback and Single Sign Out Callback to 17 | a Rack Middleware. 18 | 19 | ## Version 3.1 20 | 21 | 1. Cleanup the way Ticket Store integration works 22 | 1. Improve test coverage for CASClient::Client 23 | 1. Remove dependency on activesupport (expect in Rails specific classes) 24 | 1. Support for Rails 3.0 and 3.1 25 | 26 | ## Future 27 | 28 | 1. Support for other Rubies (JRuby, Rubinius, etc.) 29 | 1. Support for Rails 3.2 30 | 31 | # Documentation Needs 32 | 33 | ## Improve/Rewrite Documentation 34 | 35 | The documentation isn't the clearest and is now a bit out of date. That 36 | needs addressing 37 | 38 | ## Examples 39 | 40 | We could use some new and/or improved examples for 41 | 42 | 1. Rails 2.3 43 | 1. Rails 3.x 44 | 1. Sinatra 45 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 2.3.9 2 | -------------------------------------------------------------------------------- /examples/rails/README: -------------------------------------------------------------------------------- 1 | This is a skeleton Rails application hooked up for CAS authentication. 2 | 3 | To try this out: 4 | 5 | 1. If you have an existing CAS server, modify the CAS client settings in 6 | config/environment.rb to point to your server. If you do not yet 7 | have a CAS server, install rubycas-server, and configure it to run on 8 | http://localhost:7777 (or modify environment.rb to your likings). 9 | 10 | 2. Run `ruby script/server` 11 | 12 | 3. Point your web browser to http://localhost:3000 13 | 14 | 4. Have a look at the source code in app/controllers/simple_example_controller.rb 15 | and app/controllers/advanced_example_controller.rb. The 16 | corresponding views under app/views might also be worth looking at. 17 | -------------------------------------------------------------------------------- /examples/rails/app/controllers/advanced_example_controller.rb: -------------------------------------------------------------------------------- 1 | # A more advanced example. 2 | # For basic usage see the SimpleExampleController. 3 | class AdvancedExampleController < ApplicationController 4 | # This will allow the user to view the index page without authentication 5 | # but will process CAS authentication data if the user already 6 | # has an SSO session open. 7 | before_filter CASClient::Frameworks::Rails::GatewayFilter, :only => :index 8 | 9 | # This requires the user to be authenticated for viewing allother pages. 10 | before_filter CASClient::Frameworks::Rails::Filter, :except => :index 11 | 12 | def index 13 | @username = session[:cas_user] 14 | 15 | @login_url = CASClient::Frameworks::Rails::Filter.login_url(self) 16 | end 17 | 18 | def my_account 19 | @username = session[:cas_user] 20 | 21 | # Additional user attributes are available if your 22 | # CAS server is configured to provide them. 23 | # See http://code.google.com/p/rubycas-server/wiki/HowToSendExtraUserAttributes 24 | @extra_attributes = session[:cas_extra_attributes] 25 | end 26 | 27 | def logout 28 | CASClient::Frameworks::Rails::Filter.logout(self) 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /examples/rails/app/controllers/application.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | end 3 | -------------------------------------------------------------------------------- /examples/rails/app/controllers/simple_example_controller.rb: -------------------------------------------------------------------------------- 1 | # This is the most basic, bare-bones example. 2 | # For advanced usage see the AdvancedExampleController. 3 | class SimpleExampleController < ApplicationController 4 | # This will force CAS authentication before the user 5 | # is allowed to access any action in this controller. 6 | before_filter CASClient::Frameworks::Rails::Filter 7 | 8 | def index 9 | @username = session[:cas_user] 10 | end 11 | 12 | def logout 13 | CASClient::Frameworks::Rails::Filter.logout(self) 14 | end 15 | 16 | end 17 | -------------------------------------------------------------------------------- /examples/rails/app/views/advanced_example/index.html.erb: -------------------------------------------------------------------------------- 1 |

AdvancedExample#index

2 | 3 | <% if @username %> 4 |

Hello, <%= @username %>! You are authenticated.

5 | <% else %> 6 |

You are not yet authenticated. <%= link_to("Login", @login_url) %> 7 | <% end %> 8 | 9 |

» <%= link_to("Go To My Account", :action => 'my_account') %>

10 | 11 | <% if @username %> 12 |

[ <%= link_to("Logout", :action => 'logout') %> ]

13 | <% end %> 14 | -------------------------------------------------------------------------------- /examples/rails/app/views/advanced_example/my_account.html.erb: -------------------------------------------------------------------------------- 1 |

AdvancedExample#my_account

2 |

<%= @username %>'s Account page

3 | 4 |

5 | Extra Attributes:
6 | <% unless @extra_attributes.blank? %> 7 | <%= debug(@extra_attributes) %> 8 | <% end %> 9 |

10 | 11 |

[ <%= link_to("Logout", :action => 'logout') %> ]

12 | -------------------------------------------------------------------------------- /examples/rails/app/views/simple_example/index.html.erb: -------------------------------------------------------------------------------- 1 |

SimpleExample#index

2 |

Hello, <%= @username %>!

3 | 4 |

» <%= link_to("Go To AdvancedExample", :controller => 'advanced_example') %>

5 | 6 |

[ <%= link_to("Logout", :action => 'logout') %> ]

7 | -------------------------------------------------------------------------------- /examples/rails/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Don't change this file! 2 | # Configure your app in config/environment.rb and config/environments/*.rb 3 | 4 | Rails.root = "#{File.dirname(__FILE__)}/.." unless defined?(Rails.root) 5 | 6 | module Rails 7 | class << self 8 | def boot! 9 | unless booted? 10 | preinitialize 11 | pick_boot.run 12 | end 13 | end 14 | 15 | def booted? 16 | defined? Rails::Initializer 17 | end 18 | 19 | def pick_boot 20 | (vendor_rails? ? VendorBoot : GemBoot).new 21 | end 22 | 23 | def vendor_rails? 24 | File.exist?("#{Rails.root}/vendor/rails") 25 | end 26 | 27 | def preinitialize 28 | load(preinitializer_path) if File.exist?(preinitializer_path) 29 | end 30 | 31 | def preinitializer_path 32 | "#{Rails.root}/config/preinitializer.rb" 33 | end 34 | end 35 | 36 | class Boot 37 | def run 38 | load_initializer 39 | Rails::Initializer.run(:set_load_path) 40 | end 41 | end 42 | 43 | class VendorBoot < Boot 44 | def load_initializer 45 | require "#{Rails.root}/vendor/rails/railties/lib/initializer" 46 | Rails::Initializer.run(:install_gem_spec_stubs) 47 | end 48 | end 49 | 50 | class GemBoot < Boot 51 | def load_initializer 52 | self.class.load_rubygems 53 | load_rails_gem 54 | require 'initializer' 55 | end 56 | 57 | def load_rails_gem 58 | if version = self.class.gem_version 59 | gem 'rails', version 60 | else 61 | gem 'rails' 62 | end 63 | rescue Gem::LoadError => load_error 64 | $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.) 65 | exit 1 66 | end 67 | 68 | class << self 69 | def rubygems_version 70 | Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion 71 | end 72 | 73 | def gem_version 74 | if defined? RAILS_GEM_VERSION 75 | RAILS_GEM_VERSION 76 | elsif ENV.include?('RAILS_GEM_VERSION') 77 | ENV['RAILS_GEM_VERSION'] 78 | else 79 | parse_gem_version(read_environment_rb) 80 | end 81 | end 82 | 83 | def load_rubygems 84 | require 'rubygems' 85 | min_version = '1.1.1' 86 | unless rubygems_version >= min_version 87 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.) 88 | exit 1 89 | end 90 | 91 | rescue LoadError 92 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org) 93 | exit 1 94 | end 95 | 96 | def parse_gem_version(text) 97 | $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/ 98 | end 99 | 100 | private 101 | def read_environment_rb 102 | File.read("#{Rails.root}/config/environment.rb") 103 | end 104 | end 105 | end 106 | end 107 | 108 | # All that for this: 109 | Rails.boot! 110 | -------------------------------------------------------------------------------- /examples/rails/config/environment.rb: -------------------------------------------------------------------------------- 1 | RAILS_GEM_VERSION = '2.1.2' unless defined? RAILS_GEM_VERSION 2 | 3 | require File.join(File.dirname(__FILE__), 'boot') 4 | 5 | Rails::Initializer.run do |config| 6 | config.time_zone = 'UTC' 7 | config.action_controller.session = { 8 | :session_key => '_rails_session', 9 | :secret => 'e2f5641ab4a3627096a2b6ca8c62cefe53f572906ad6a5fb1c949d183a0' 10 | } 11 | config.frameworks -= [:active_record] 12 | end 13 | 14 | 15 | # Basic CAS client configuration 16 | 17 | require 'casclient' 18 | require 'casclient/frameworks/rails/filter' 19 | 20 | CASClient::Frameworks::Rails::Filter.configure( 21 | :cas_base_url => "https://mzukowski.urbacon.net:6543/cas" 22 | ) 23 | 24 | 25 | # More complicated configuration 26 | 27 | #cas_logger = CASClient::Logger.new(Rails.root+'/log/cas.log') 28 | #cas_logger.level = Logger::DEBUG 29 | # 30 | #CASClient::Frameworks::Rails::Filter.configure( 31 | # :cas_base_url => "https://localhost:7778/", 32 | # :login_url => "https://localhost:7778/login", 33 | # :logout_url => "https://localhost:7778/logout", 34 | # :validate_url => "https://localhost:7778/proxyValidate", 35 | # :session_username_key => :cas_user, 36 | # :session_extra_attributes_key => :cas_extra_attributes 37 | # :logger => cas_logger, 38 | # :authenticate_on_every_request => true 39 | #) 40 | -------------------------------------------------------------------------------- /examples/rails/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | # Settings specified here will take precedence over those in config/environment.rb 2 | 3 | # In the development environment your application's code is reloaded on 4 | # every request. This slows down response time but is perfect for development 5 | # since you don't have to restart the webserver when you make code changes. 6 | config.cache_classes = false 7 | 8 | # Log error messages when you accidentally call methods on nil. 9 | config.whiny_nils = true 10 | 11 | # Show full error reports and disable caching 12 | config.action_controller.consider_all_requests_local = true 13 | config.action_view.debug_rjs = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send 17 | config.action_mailer.raise_delivery_errors = false -------------------------------------------------------------------------------- /examples/rails/config/environments/production.rb: -------------------------------------------------------------------------------- 1 | # Settings specified here will take precedence over those in config/environment.rb 2 | 3 | # The production environment is meant for finished, "live" apps. 4 | # Code is not reloaded between requests 5 | config.cache_classes = true 6 | 7 | # Use a different logger for distributed setups 8 | # config.logger = SyslogLogger.new 9 | 10 | # Full error reports are disabled and caching is turned on 11 | config.action_controller.consider_all_requests_local = false 12 | config.action_controller.perform_caching = true 13 | config.action_view.cache_template_loading = true 14 | 15 | # Use a different cache store in production 16 | # config.cache_store = :mem_cache_store 17 | 18 | # Enable serving of images, stylesheets, and javascripts from an asset server 19 | # config.action_controller.asset_host = "http://assets.example.com" 20 | 21 | # Disable delivery errors, bad email addresses will be ignored 22 | # config.action_mailer.raise_delivery_errors = false 23 | -------------------------------------------------------------------------------- /examples/rails/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | # Settings specified here will take precedence over those in config/environment.rb 2 | 3 | # The test environment is used exclusively to run your application's 4 | # test suite. You never need to work with it otherwise. Remember that 5 | # your test database is "scratch space" for the test suite and is wiped 6 | # and recreated between test runs. Don't rely on the data there! 7 | config.cache_classes = true 8 | 9 | # Log error messages when you accidentally call methods on nil. 10 | config.whiny_nils = true 11 | 12 | # Show full error reports and disable caching 13 | config.action_controller.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Disable request forgery protection in test environment 17 | config.action_controller.allow_forgery_protection = false 18 | 19 | # Tell Action Mailer not to deliver emails to the real world. 20 | # The :test delivery method accumulates sent emails in the 21 | # ActionMailer::Base.deliveries array. 22 | config.action_mailer.delivery_method = :test 23 | -------------------------------------------------------------------------------- /examples/rails/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format 4 | # (all these examples are active by default): 5 | # ActiveSupport::Inflector.inflections do |inflect| 6 | # inflect.plural /^(ox)$/i, '\1en' 7 | # inflect.singular /^(ox)en/i, '\1' 8 | # inflect.irregular 'person', 'people' 9 | # inflect.uncountable %w( fish sheep ) 10 | # end 11 | -------------------------------------------------------------------------------- /examples/rails/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | # Mime::Type.register_alias "text/html", :iphone 6 | -------------------------------------------------------------------------------- /examples/rails/config/initializers/new_rails_defaults.rb: -------------------------------------------------------------------------------- 1 | # These settings change the behavior of Rails 2 apps and will be defaults 2 | # for Rails 3. You can remove this initializer when Rails 3 is released. 3 | 4 | if defined?(ActiveRecord) 5 | # Include Active Record class name as root for JSON serialized output. 6 | ActiveRecord::Base.include_root_in_json = true 7 | 8 | # Store the full class name (including module namespace) in STI type column. 9 | ActiveRecord::Base.store_full_sti_class = true 10 | end 11 | 12 | # Use ISO 8601 format for JSON serialized times and dates. 13 | ActiveSupport.use_standard_json_time_format = true 14 | 15 | # Don't escape HTML entities in JSON, leave that for the #json_escape helper. 16 | # if you're including raw json in an HTML page. 17 | ActiveSupport.escape_html_entities_in_json = false -------------------------------------------------------------------------------- /examples/rails/config/routes.rb: -------------------------------------------------------------------------------- 1 | ActionController::Routing::Routes.draw do |map| 2 | map.root :controller => "simple_example" 3 | map.connect ':controller/:action/:id' 4 | end 5 | -------------------------------------------------------------------------------- /examples/rails/log/development.log: -------------------------------------------------------------------------------- 1 | 2 | 3 | Processing SimpleExampleController#index (for 127.0.0.1 at 2008-11-20 12:05:13) [GET] 4 | Session ID: 917a1a0262589e0f5073fd47a17a0743 5 | Parameters: {"action"=>"index", "controller"=>"simple_example"} 6 | Guessed service url: "http://localhost:3000/" 7 | Redirecting to "https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2F" 8 | Redirected to https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2F 9 | Filter chain halted as [CASClient::Frameworks::Rails::Filter] rendered_or_redirected. 10 | Completed in 0.00075 (1331 reqs/sec) | 302 Found [http://localhost/] 11 | 12 | 13 | Processing SimpleExampleController#index (for 127.0.0.1 at 2008-11-20 12:05:13) [GET] 14 | Session ID: BAh7CTofY2FzX3ZhbGlkYXRpb25fcmV0cnlfY291bnRpADoYY2FzX3NlbnRf 15 | dG9fZ2F0ZXdheUY6HXByZXZpb3VzX3JlZGlyZWN0X3RvX2Nhc0l1OglUaW1l 16 | DZEqG4DJD9QUBjofQG1hcnNoYWxfd2l0aF91dGNfY29lcmNpb25GIgpmbGFz 17 | aElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA 18 | dXNlZHsA--b3458ca581ced2c4bb7601e00b9dc7e00c91fcc6 19 | Parameters: {"ticket"=>"ST-1227200713rA9077D6EEE2B0745AF", "action"=>"index", "controller"=>"simple_example"} 20 | Request contains ticket "ST-1227200713rA9077D6EEE2B0745AF". 21 | Guessed service url: "http://localhost:3000/" 22 | Requesting CAS response for URI https://mzukowski.urbacon.net:6543/cas/proxyValidate?ticket=ST-1227200713rA9077D6EEE2B0745AF&service=http%3A%2F%2Flocalhost%3A3000%2F 23 | CAS server responded with #: 24 | mzukowskiMatt Zukowskimzukowski@urbacon.net 25 | Ticket "ST-1227200713rA9077D6EEE2B0745AF" for service "http://localhost:3000/" belonging to user "mzukowski" is VALID. 26 | Extra user attributes provided along with ticket "ST-1227200713rA9077D6EEE2B0745AF": {"cn"=>"Matt Zukowski", "mail"=>"mzukowski@urbacon.net"}. 27 | Wrote service session lookup file to "/home/URBACON/mzukowski/workspace/rubycas-client2/examples/rails/tmp/sessions/cas_sess.ST-1227200713rA9077D6EEE2B0745AF" with session id "BAh7CTofY2FzX3ZhbGlkYXRpb25fcmV0cnlfY291bnRpADoYY2FzX3NlbnRf\ndG9fZ2F0ZXdheUY6HXByZXZpb3VzX3JlZGlyZWN0X3RvX2Nhc0l1OglUaW1l\nDZEqG4DJD9QUBjofQG1hcnNoYWxfd2l0aF91dGNfY29lcmNpb25GIgpmbGFz\naElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA\ndXNlZHsA--b3458ca581ced2c4bb7601e00b9dc7e00c91fcc6". 28 | Rendering simple_example/index 29 | Completed in 0.02824 (35 reqs/sec) | Rendering: 0.00208 (7%) | 200 OK [http://localhost/?ticket=ST-1227200713rA9077D6EEE2B0745AF] 30 | 31 | 32 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:05:20) [GET] 33 | Session ID: BAh7DTofY2FzX3ZhbGlkYXRpb25fcmV0cnlfY291bnRpADoZY2FzX2V4dHJh 34 | X2F0dHJpYnV0ZXNDOh5IYXNoV2l0aEluZGlmZmVyZW50QWNjZXNzewciB2Nu 35 | IhJNYXR0IFp1a293c2tpIgltYWlsIhptenVrb3dza2lAdXJiYWNvbi5uZXQ6 36 | GmNhc19sYXN0X3ZhbGlkX3RpY2tldG86HUNBU0NsaWVudDo6U2VydmljZVRp 37 | Y2tldAk6DEB0aWNrZXQiJVNULTEyMjcyMDA3MTNyQTkwNzdENkVFRTJCMDc0 38 | NUFGOg5AcmVzcG9uc2VvOiJDQVNDbGllbnQ6OlZhbGlkYXRpb25SZXNwb25z 39 | ZQo6FEBwYXJzZV9kYXRldGltZUl1OglUaW1lDZEqG4BX59QUBjofQG1hcnNo 40 | YWxfd2l0aF91dGNfY29lcmNpb25GOgpAdXNlciIObXp1a293c2tpOglAeG1s 41 | bzoTUkVYTUw6OkVsZW1lbnQNOgxAcHJlZml4IghjYXM6DkBlbGVtZW50c286 42 | FFJFWE1MOjpFbGVtZW50cwY6DUBlbGVtZW50QBA6EEBhdHRyaWJ1dGVzSUM6 43 | FlJFWE1MOjpBdHRyaWJ1dGVzewAGOxZAEDoTQGV4cGFuZGVkX25hbWUiHmNh 44 | czphdXRoZW50aWNhdGlvblN1Y2Nlc3M6DkBjaGlsZHJlblsIbzsSDzsTIghj 45 | YXM7FG87FQY7FkAWOh1AaWdub3JlX3doaXRlc3BhY2Vfbm9kZXNGOxdJQzsY 46 | ewAGOxZAFjoQQHdoaXRlc3BhY2VUOxkiDWNhczp1c2VyOxpbBm86EFJFWE1M 47 | OjpUZXh0CzoSQHVubm9ybWFsaXplZCIObXp1a293c2tpOgxAc3RyaW5nIg5t 48 | enVrb3dza2k6EEBub3JtYWxpemVkMDoTQGVudGl0eV9maWx0ZXIwOglAcmF3 49 | VDoMQHBhcmVudEAWOg1AY29udGV4dHsAOgpAbmFtZSIJdXNlcjsjQBBvOxIQ 50 | OxMiADsUbzsVBjsWQCE7G0Y7F0lDOxh7AAY7FkAhOxxUOxkiB2NuOxpbBm87 51 | HQs7HjA7HyISTWF0dCBadWtvd3NraTsgMDshMDsiVDsjQCE7JEAfOyUiB2Nu 52 | Og9AbmFtZXNwYWNlIgA7I0AQbzsSEDsTIgA7FG87FQY7FkArOxtGOxdJQzsY 53 | ewAGOxZAKzscVDsZIgltYWlsOxpbBm87HQs7HjA7HyIabXp1a293c2tpQHVy 54 | YmFjb24ubmV0OyAwOyEwOyJUOyNAKzskQB87JSIJbWFpbDsmIgA7I0AQOyRA 55 | HzslIhphdXRoZW50aWNhdGlvblN1Y2Nlc3M7I287Eg07EyIIY2FzOxRvOxUG 56 | OxZANjsXSUM7GHsGIghjYXNvOhVSRVhNTDo6QXR0cmlidXRlDDsTIgp4bWxu 57 | czsWQDY6C0B2YWx1ZSIfaHR0cDovL3d3dy55YWxlLmVkdS90cC9jYXM7HiIf 58 | aHR0cDovL3d3dy55YWxlLmVkdS90cC9jYXM7GSIOeG1sbnM6Y2FzOyAwOyUi 59 | CGNhcwY7FkA2OxkiGGNhczpzZXJ2aWNlUmVzcG9uc2U7GlsGQBA7JEAfOyUi 60 | FHNlcnZpY2VSZXNwb25zZTsjbzoUUkVYTUw6OkRvY3VtZW50DjsTIgA7FG87 61 | FQY7FkBEOxdJQzsYewAGOxZARDsZIg5VTkRFRklORUQ7GlsGQDY7JEAfOyUi 62 | DlVOREVGSU5FRDsmIgA7IzA6DkBwcm90b2NvbGYGMjoWQGV4dHJhX2F0dHJp 63 | YnV0ZXN7B0AHQAhACUAKOgtAcmVuZXcwOg1Ac2VydmljZSIbaHR0cDovL2xv 64 | Y2FsaG9zdDozMDAwLzoSY2FzZmlsdGVydXNlckAPOhhjYXNfc2VudF90b19n 65 | YXRld2F5RiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZs 66 | YXNoSGFzaHsABjoKQHVzZWR7ADodcHJldmlvdXNfcmVkaXJlY3RfdG9fY2Fz 67 | SXU7Dg2RKhuAyQ/UFAY7D0Y6DWNhc191c2VyIg5tenVrb3dza2k=--e428be7c02bb1bb56e8603775871520420754a92 68 | Parameters: {"action"=>"index", "controller"=>"advanced_example"} 69 | Existing local CAS session detected for "mzukowski". Previous ticket "ST-1227200713rA9077D6EEE2B0745AF" will be re-used. 70 | Rendering advanced_example/index 71 | Completed in 0.00290 (344 reqs/sec) | Rendering: 0.00130 (44%) | 200 OK [http://localhost/advanced_example] 72 | 73 | 74 | Processing AdvancedExampleController#my_account (for 127.0.0.1 at 2008-11-20 12:05:22) [GET] 75 | Session ID: BAh7DTofY2FzX3ZhbGlkYXRpb25fcmV0cnlfY291bnRpADoZY2FzX2V4dHJh 76 | X2F0dHJpYnV0ZXNDOh5IYXNoV2l0aEluZGlmZmVyZW50QWNjZXNzewciB2Nu 77 | IhJNYXR0IFp1a293c2tpIgltYWlsIhptenVrb3dza2lAdXJiYWNvbi5uZXQ6 78 | GmNhc19sYXN0X3ZhbGlkX3RpY2tldG86HUNBU0NsaWVudDo6U2VydmljZVRp 79 | Y2tldAk6DEB0aWNrZXQiJVNULTEyMjcyMDA3MTNyQTkwNzdENkVFRTJCMDc0 80 | NUFGOg5AcmVzcG9uc2VvOiJDQVNDbGllbnQ6OlZhbGlkYXRpb25SZXNwb25z 81 | ZQo6FEBwYXJzZV9kYXRldGltZUl1OglUaW1lDZEqG4BX59QUBjofQG1hcnNo 82 | YWxfd2l0aF91dGNfY29lcmNpb25GOgpAdXNlciIObXp1a293c2tpOglAeG1s 83 | bzoTUkVYTUw6OkVsZW1lbnQNOgxAcHJlZml4IghjYXM6DkBlbGVtZW50c286 84 | FFJFWE1MOjpFbGVtZW50cwY6DUBlbGVtZW50QBA6EEBhdHRyaWJ1dGVzSUM6 85 | FlJFWE1MOjpBdHRyaWJ1dGVzewAGOxZAEDoTQGV4cGFuZGVkX25hbWUiHmNh 86 | czphdXRoZW50aWNhdGlvblN1Y2Nlc3M6DkBjaGlsZHJlblsIbzsSDzsTIghj 87 | YXM7FG87FQY7FkAWOxdJQzsYewAGOxZAFjodQGlnbm9yZV93aGl0ZXNwYWNl 88 | X25vZGVzRjoQQHdoaXRlc3BhY2VUOxkiDWNhczp1c2VyOxpbBm86EFJFWE1M 89 | OjpUZXh0CzoSQHVubm9ybWFsaXplZCIObXp1a293c2tpOgxAc3RyaW5nIg5t 90 | enVrb3dza2k6EEBub3JtYWxpemVkMDoJQHJhd1Q6E0BlbnRpdHlfZmlsdGVy 91 | MDoMQHBhcmVudEAWOg1AY29udGV4dHsAOgpAbmFtZSIJdXNlcjsjQBBvOxIQ 92 | OxMiADsUbzsVBjsWQCE7F0lDOxh7AAY7FkAhOxtGOxxUOxkiB2NuOxpbBm87 93 | HQs7HjA7HyISTWF0dCBadWtvd3NraTsgMDshVDsiMDsjQCE7JEAfOg9AbmFt 94 | ZXNwYWNlIgA7JSIHY247I0AQbzsSEDsTIgA7FG87FQY7FkArOxdJQzsYewAG 95 | OxZAKzsbRjscVDsZIgltYWlsOxpbBm87HQs7HjA7HyIabXp1a293c2tpQHVy 96 | YmFjb24ubmV0OyAwOyFUOyIwOyNAKzskQB87JiIAOyUiCW1haWw7I0AQOyRA 97 | HzslIhphdXRoZW50aWNhdGlvblN1Y2Nlc3M7I287Eg07EyIIY2FzOxRvOxUG 98 | OxZANjsXSUM7GHsGIghjYXNvOhVSRVhNTDo6QXR0cmlidXRlDDsWQDY7EyIK 99 | eG1sbnM6C0B2YWx1ZSIfaHR0cDovL3d3dy55YWxlLmVkdS90cC9jYXM7HiIf 100 | aHR0cDovL3d3dy55YWxlLmVkdS90cC9jYXM7GSIOeG1sbnM6Y2FzOyAwOyUi 101 | CGNhcwY7FkA2OxkiGGNhczpzZXJ2aWNlUmVzcG9uc2U7GlsGQBA7JEAfOyUi 102 | FHNlcnZpY2VSZXNwb25zZTsjbzoUUkVYTUw6OkRvY3VtZW50DjsTIgA7FG87 103 | FQY7FkBEOxdJQzsYewAGOxZARDsZIg5VTkRFRklORUQ7GlsGQDY7JEAfOyYi 104 | ADslIg5VTkRFRklORUQ7IzA6DkBwcm90b2NvbGYGMjoWQGV4dHJhX2F0dHJp 105 | YnV0ZXN7B0AHQAhACUAKOgtAcmVuZXcwOg1Ac2VydmljZSIbaHR0cDovL2xv 106 | Y2FsaG9zdDozMDAwLzoSY2FzZmlsdGVydXNlckAPOhhjYXNfc2VudF90b19n 107 | YXRld2F5RjodcHJldmlvdXNfcmVkaXJlY3RfdG9fY2FzSXU7Dg2RKhuAyQ/U 108 | FAY7D0YiCmZsYXNoSUM6J0FjdGlvbkNvbnRyb2xsZXI6OkZsYXNoOjpGbGFz 109 | aEhhc2h7AAY6CkB1c2VkewA6DWNhc191c2VyIg5tenVrb3dza2k=--42885a608a276bbc90475fedf50fe9651d3dbafc 110 | Parameters: {"action"=>"my_account", "controller"=>"advanced_example"} 111 | Existing local CAS session detected for "mzukowski". Previous ticket "ST-1227200713rA9077D6EEE2B0745AF" will be re-used. 112 | Rendering advanced_example/my_account 113 | Completed in 0.00314 (318 reqs/sec) | Rendering: 0.00153 (48%) | 200 OK [http://localhost/advanced_example/my_account] 114 | 115 | 116 | Processing AdvancedExampleController#logout (for 127.0.0.1 at 2008-11-20 12:05:31) [GET] 117 | Session ID: BAh7DTofY2FzX3ZhbGlkYXRpb25fcmV0cnlfY291bnRpADoZY2FzX2V4dHJh 118 | X2F0dHJpYnV0ZXNDOh5IYXNoV2l0aEluZGlmZmVyZW50QWNjZXNzewciB2Nu 119 | IhJNYXR0IFp1a293c2tpIgltYWlsIhptenVrb3dza2lAdXJiYWNvbi5uZXQ6 120 | GmNhc19sYXN0X3ZhbGlkX3RpY2tldG86HUNBU0NsaWVudDo6U2VydmljZVRp 121 | Y2tldAk6DEB0aWNrZXQiJVNULTEyMjcyMDA3MTNyQTkwNzdENkVFRTJCMDc0 122 | NUFGOg5AcmVzcG9uc2VvOiJDQVNDbGllbnQ6OlZhbGlkYXRpb25SZXNwb25z 123 | ZQo6FEBwYXJzZV9kYXRldGltZUl1OglUaW1lDZEqG4BX59QUBjofQG1hcnNo 124 | YWxfd2l0aF91dGNfY29lcmNpb25GOgpAdXNlciIObXp1a293c2tpOglAeG1s 125 | bzoTUkVYTUw6OkVsZW1lbnQNOgxAcHJlZml4IghjYXM6DkBlbGVtZW50c286 126 | FFJFWE1MOjpFbGVtZW50cwY6DUBlbGVtZW50QBA6EEBhdHRyaWJ1dGVzSUM6 127 | FlJFWE1MOjpBdHRyaWJ1dGVzewAGOxZAEDoTQGV4cGFuZGVkX25hbWUiHmNh 128 | czphdXRoZW50aWNhdGlvblN1Y2Nlc3M6DkBjaGlsZHJlblsIbzsSDzsTIghj 129 | YXM7FG87FQY7FkAWOh1AaWdub3JlX3doaXRlc3BhY2Vfbm9kZXNGOxdJQzsY 130 | ewAGOxZAFjoQQHdoaXRlc3BhY2VUOxkiDWNhczp1c2VyOxpbBm86EFJFWE1M 131 | OjpUZXh0CzoSQHVubm9ybWFsaXplZCIObXp1a293c2tpOgxAc3RyaW5nIg5t 132 | enVrb3dza2k6EEBub3JtYWxpemVkMDoTQGVudGl0eV9maWx0ZXIwOglAcmF3 133 | VDoMQHBhcmVudEAWOg1AY29udGV4dHsAOgpAbmFtZSIJdXNlcjsjQBBvOxIQ 134 | OxMiADsUbzsVBjsWQCE7G0Y7F0lDOxh7AAY7FkAhOxxUOxkiB2NuOxpbBm87 135 | HQs7HjA7HyISTWF0dCBadWtvd3NraTsgMDshMDsiVDsjQCE7JEAfOyUiB2Nu 136 | Og9AbmFtZXNwYWNlIgA7I0AQbzsSEDsTIgA7FG87FQY7FkArOxtGOxdJQzsY 137 | ewAGOxZAKzscVDsZIgltYWlsOxpbBm87HQs7HjA7HyIabXp1a293c2tpQHVy 138 | YmFjb24ubmV0OyAwOyEwOyJUOyNAKzskQB87JSIJbWFpbDsmIgA7I0AQOyRA 139 | HzslIhphdXRoZW50aWNhdGlvblN1Y2Nlc3M7I287Eg07EyIIY2FzOxRvOxUG 140 | OxZANjsXSUM7GHsGIghjYXNvOhVSRVhNTDo6QXR0cmlidXRlDDsTIgp4bWxu 141 | czsWQDY6C0B2YWx1ZSIfaHR0cDovL3d3dy55YWxlLmVkdS90cC9jYXM7HiIf 142 | aHR0cDovL3d3dy55YWxlLmVkdS90cC9jYXM7GSIOeG1sbnM6Y2FzOyAwOyUi 143 | CGNhcwY7FkA2OxkiGGNhczpzZXJ2aWNlUmVzcG9uc2U7GlsGQBA7JEAfOyUi 144 | FHNlcnZpY2VSZXNwb25zZTsjbzoUUkVYTUw6OkRvY3VtZW50DjsTIgA7FG87 145 | FQY7FkBEOxdJQzsYewAGOxZARDsZIg5VTkRFRklORUQ7GlsGQDY7JEAfOyUi 146 | DlVOREVGSU5FRDsmIgA7IzA6DkBwcm90b2NvbGYGMjoWQGV4dHJhX2F0dHJp 147 | YnV0ZXN7B0AHQAhACUAKOgtAcmVuZXcwOg1Ac2VydmljZSIbaHR0cDovL2xv 148 | Y2FsaG9zdDozMDAwLzoSY2FzZmlsdGVydXNlckAPOhhjYXNfc2VudF90b19n 149 | YXRld2F5RiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZs 150 | YXNoSGFzaHsABjoKQHVzZWR7ADodcHJldmlvdXNfcmVkaXJlY3RfdG9fY2Fz 151 | SXU7Dg2RKhuAyQ/UFAY7D0Y6DWNhc191c2VyIg5tenVrb3dza2k=--e428be7c02bb1bb56e8603775871520420754a92 152 | Parameters: {"action"=>"logout", "controller"=>"advanced_example"} 153 | Existing local CAS session detected for "mzukowski". Previous ticket "ST-1227200713rA9077D6EEE2B0745AF" will be re-used. 154 | Redirected to https://mzukowski.urbacon.net:6543/cas/logout?destination=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example%2Fmy_account 155 | Completed in 0.10119 (9 reqs/sec) | 302 Found [http://localhost/advanced_example/logout] 156 | 157 | 158 | Processing SimpleExampleController#index (for 127.0.0.1 at 2008-11-20 12:08:18) [POST] 159 | Session ID: 9dccf65589fd53880e80a8e84608169c 160 | Parameters: {"action"=>"index", "logoutRequest"=>"\n\nST-1227200713rA9077D6EEE2B0745AF\n", "controller"=>"simple_example"} 161 | 162 | 163 | ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken): 164 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/request_forgery_protection.rb:86:in `verify_authenticity_token' 165 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/callbacks.rb:173:in `send' 166 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/callbacks.rb:173:in `evaluate_method' 167 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/callbacks.rb:161:in `call' 168 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:191:in `call' 169 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:591:in `run_before_filters' 170 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:577:in `call_filters' 171 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:572:in `perform_action_without_benchmark' 172 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 173 | /usr/lib/ruby/1.8/benchmark.rb:293:in `measure' 174 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 175 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/rescue.rb:201:in `perform_action' 176 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `send' 177 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `process_without_filters' 178 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:568:in `process_without_session_management_support' 179 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/session_management.rb:130:in `process' 180 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:389:in `process' 181 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:149:in `handle_request' 182 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:107:in `dispatch' 183 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `synchronize' 184 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `dispatch' 185 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:120:in `dispatch_cgi' 186 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:35:in `dispatch' 187 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:76:in `process' 188 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `synchronize' 189 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `process' 190 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:159:in `process_client' 191 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `each' 192 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `process_client' 193 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 194 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `initialize' 195 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `new' 196 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 197 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `initialize' 198 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `new' 199 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `run' 200 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:282:in `run' 201 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `each' 202 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `run' 203 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:128:in `run' 204 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/command.rb:212:in `run' 205 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:281 206 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 207 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 208 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 209 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 210 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/servers/mongrel.rb:64 211 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 212 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 213 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 214 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 215 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 216 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/server.rb:39 217 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 218 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 219 | script/server:3 220 | 221 | Rendering /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/templates/rescues/layout.erb (unprocessable_entity) 222 | 223 | 224 | Processing AdvancedExampleController#my_account (for 127.0.0.1 at 2008-11-20 12:08:23) [GET] 225 | Session ID: BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo 226 | SGFzaHsABjoKQHVzZWR7AA==--3ac0dad26b5ba8bf00d4a6485f54f64cd01e94a4 227 | Parameters: {"ticket"=>"ST-1227200903rCC9CF1C7E7B5EF7FA3", "action"=>"my_account", "controller"=>"advanced_example"} 228 | Request contains ticket "ST-1227200903rCC9CF1C7E7B5EF7FA3". 229 | Guessed service url: "http://localhost:3000/advanced_example/my_account" 230 | Requesting CAS response for URI https://mzukowski.urbacon.net:6543/cas/proxyValidate?ticket=ST-1227200903rCC9CF1C7E7B5EF7FA3&service=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example%2Fmy_account 231 | CAS server responded with #: 232 | mzukowskiMatt Zukowskimzukowski@urbacon.net 233 | Ticket "ST-1227200903rCC9CF1C7E7B5EF7FA3" for service "http://localhost:3000/advanced_example/my_account" belonging to user "mzukowski" is VALID. 234 | Extra user attributes provided along with ticket "ST-1227200903rCC9CF1C7E7B5EF7FA3": {"cn"=>"Matt Zukowski", "mail"=>"mzukowski@urbacon.net"}. 235 | Wrote service session lookup file to "/home/URBACON/mzukowski/workspace/rubycas-client2/examples/rails/tmp/sessions/cas_sess.ST-1227200903rCC9CF1C7E7B5EF7FA3" with session id "BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo\nSGFzaHsABjoKQHVzZWR7AA==--3ac0dad26b5ba8bf00d4a6485f54f64cd01e94a4". 236 | Rendering advanced_example/my_account 237 | Completed in 0.02754 (36 reqs/sec) | Rendering: 0.00078 (2%) | 200 OK [http://localhost/advanced_example/my_account?ticket=ST-1227200903rCC9CF1C7E7B5EF7FA3] 238 | 239 | 240 | Processing AdvancedExampleController#logout (for 127.0.0.1 at 2008-11-20 12:08:25) [GET] 241 | Session ID: BAh7CjoZY2FzX2V4dHJhX2F0dHJpYnV0ZXNDOh5IYXNoV2l0aEluZGlmZmVy 242 | ZW50QWNjZXNzewciB2NuIhJNYXR0IFp1a293c2tpIgltYWlsIhptenVrb3dz 243 | a2lAdXJiYWNvbi5uZXQ6GmNhc19sYXN0X3ZhbGlkX3RpY2tldG86HUNBU0Ns 244 | aWVudDo6U2VydmljZVRpY2tldAk6DEB0aWNrZXQiJVNULTEyMjcyMDA5MDNy 245 | Q0M5Q0YxQzdFN0I1RUY3RkEzOg5AcmVzcG9uc2VvOiJDQVNDbGllbnQ6OlZh 246 | bGlkYXRpb25SZXNwb25zZQo6FEBwYXJzZV9kYXRldGltZUl1OglUaW1lDZEq 247 | G4BdvXMhBjofQG1hcnNoYWxfd2l0aF91dGNfY29lcmNpb25GOgpAdXNlciIO 248 | bXp1a293c2tpOglAeG1sbzoTUkVYTUw6OkVsZW1lbnQNOgxAcHJlZml4Ighj 249 | YXM6DkBlbGVtZW50c286FFJFWE1MOjpFbGVtZW50cwY6DUBlbGVtZW50QBA6 250 | EEBhdHRyaWJ1dGVzSUM6FlJFWE1MOjpBdHRyaWJ1dGVzewAGOxVAEDoTQGV4 251 | cGFuZGVkX25hbWUiHmNhczphdXRoZW50aWNhdGlvblN1Y2Nlc3M6DkBjaGls 252 | ZHJlblsIbzsRDzsSIghjYXM7E287FAY7FUAWOh1AaWdub3JlX3doaXRlc3Bh 253 | Y2Vfbm9kZXNGOxZJQzsXewAGOxVAFjoQQHdoaXRlc3BhY2VUOxgiDWNhczp1 254 | c2VyOxlbBm86EFJFWE1MOjpUZXh0CzoSQHVubm9ybWFsaXplZCIObXp1a293 255 | c2tpOgxAc3RyaW5nIg5tenVrb3dza2k6EEBub3JtYWxpemVkMDoTQGVudGl0 256 | eV9maWx0ZXIwOglAcmF3VDoMQHBhcmVudEAWOg1AY29udGV4dHsAOgpAbmFt 257 | ZSIJdXNlcjsiQBBvOxEQOxIiADsTbzsUBjsVQCE7GkY7FklDOxd7AAY7FUAh 258 | OxtUOxgiB2NuOxlbBm87HAs7HTA7HiISTWF0dCBadWtvd3NraTsfMDsgMDsh 259 | VDsiQCE7I0AfOyQiB2NuOg9AbmFtZXNwYWNlIgA7IkAQbzsREDsSIgA7E287 260 | FAY7FUArOxpGOxZJQzsXewAGOxVAKzsbVDsYIgltYWlsOxlbBm87HAs7HTA7 261 | HiIabXp1a293c2tpQHVyYmFjb24ubmV0Ox8wOyAwOyFUOyJAKzsjQB87JCIJ 262 | bWFpbDslIgA7IkAQOyNAHzskIhphdXRoZW50aWNhdGlvblN1Y2Nlc3M7Im87 263 | EQ07EiIIY2FzOxNvOxQGOxVANjsWSUM7F3sGIghjYXNvOhVSRVhNTDo6QXR0 264 | cmlidXRlDDsSIgp4bWxuczsVQDY6C0B2YWx1ZSIfaHR0cDovL3d3dy55YWxl 265 | LmVkdS90cC9jYXM7HSIfaHR0cDovL3d3dy55YWxlLmVkdS90cC9jYXM7GCIO 266 | eG1sbnM6Y2FzOx8wOyQiCGNhcwY7FUA2OxgiGGNhczpzZXJ2aWNlUmVzcG9u 267 | c2U7GVsGQBA7I0AfOyQiFHNlcnZpY2VSZXNwb25zZTsibzoUUkVYTUw6OkRv 268 | Y3VtZW50DjsSIgA7E287FAY7FUBEOxZJQzsXewAGOxVARDsYIg5VTkRFRklO 269 | RUQ7GVsGQDY7I0AfOyQiDlVOREVGSU5FRDslIgA7IjA6DkBwcm90b2NvbGYG 270 | MjoWQGV4dHJhX2F0dHJpYnV0ZXN7B0AHQAhACUAKOgtAcmVuZXcwOg1Ac2Vy 271 | dmljZSI2aHR0cDovL2xvY2FsaG9zdDozMDAwL2FkdmFuY2VkX2V4YW1wbGUv 272 | bXlfYWNjb3VudDoSY2FzZmlsdGVydXNlckAPIgpmbGFzaElDOidBY3Rpb25D 273 | b250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsAOg1jYXNf 274 | dXNlciIObXp1a293c2tp--26828c4722e9e049cbdad7d8fa0dddb878618630 275 | Parameters: {"action"=>"logout", "controller"=>"advanced_example"} 276 | Existing local CAS session detected for "mzukowski". Previous ticket "ST-1227200903rCC9CF1C7E7B5EF7FA3" will be re-used. 277 | Redirected to https://mzukowski.urbacon.net:6543/cas/logout?destination=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example%2Fmy_account 278 | Completed in 0.00290 (344 reqs/sec) | 302 Found [http://localhost/advanced_example/logout] 279 | 280 | 281 | Processing AdvancedExampleController#my_account (for 127.0.0.1 at 2008-11-20 12:08:25) [POST] 282 | Session ID: af9c2c3727f1e3c92c6029fbc68c9973 283 | Parameters: {"action"=>"my_account", "logoutRequest"=>"\n\nST-1227200903rCC9CF1C7E7B5EF7FA3\n", "controller"=>"advanced_example"} 284 | 285 | 286 | ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken): 287 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/request_forgery_protection.rb:86:in `verify_authenticity_token' 288 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/callbacks.rb:173:in `send' 289 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/callbacks.rb:173:in `evaluate_method' 290 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/callbacks.rb:161:in `call' 291 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:191:in `call' 292 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:591:in `run_before_filters' 293 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:577:in `call_filters' 294 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:572:in `perform_action_without_benchmark' 295 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 296 | /usr/lib/ruby/1.8/benchmark.rb:293:in `measure' 297 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 298 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/rescue.rb:201:in `perform_action' 299 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `send' 300 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `process_without_filters' 301 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:568:in `process_without_session_management_support' 302 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/session_management.rb:130:in `process' 303 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:389:in `process' 304 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:149:in `handle_request' 305 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:107:in `dispatch' 306 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `synchronize' 307 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `dispatch' 308 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:120:in `dispatch_cgi' 309 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:35:in `dispatch' 310 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:76:in `process' 311 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `synchronize' 312 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `process' 313 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:159:in `process_client' 314 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `each' 315 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `process_client' 316 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 317 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `initialize' 318 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `new' 319 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 320 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `initialize' 321 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `new' 322 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `run' 323 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:282:in `run' 324 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `each' 325 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `run' 326 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:128:in `run' 327 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/command.rb:212:in `run' 328 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:281 329 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 330 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 331 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 332 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 333 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/servers/mongrel.rb:64 334 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 335 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 336 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 337 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 338 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 339 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/server.rb:39 340 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 341 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 342 | script/server:3 343 | 344 | Rendering /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/templates/rescues/layout.erb (unprocessable_entity) 345 | 346 | 347 | Processing AdvancedExampleController#my_account (for 127.0.0.1 at 2008-11-20 12:31:32) [GET] 348 | Session ID: BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo 349 | SGFzaHsABjoKQHVzZWR7AA==--3ac0dad26b5ba8bf00d4a6485f54f64cd01e94a4 350 | Parameters: {"ticket"=>"ST-1227202292r61123E3CCB49081665", "action"=>"my_account", "controller"=>"advanced_example"} 351 | Request contains ticket "ST-1227202292r61123E3CCB49081665". 352 | Guessed service url: "http://localhost:3000/advanced_example/my_account" 353 | Requesting CAS response for URI https://mzukowski.urbacon.net:6543/cas/proxyValidate?ticket=ST-1227202292r61123E3CCB49081665&service=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example%2Fmy_account 354 | CAS server responded with #: 355 | mzukowskiMatt Zukowskimzukowski@urbacon.net 356 | Ticket "ST-1227202292r61123E3CCB49081665" for service "http://localhost:3000/advanced_example/my_account" belonging to user "mzukowski" is VALID. 357 | Extra user attributes provided along with ticket "ST-1227202292r61123E3CCB49081665": {"cn"=>"Matt Zukowski", "mail"=>"mzukowski@urbacon.net"}. 358 | Wrote service session lookup file to "/home/URBACON/mzukowski/workspace/rubycas-client2/examples/rails/tmp/sessions/cas_sess.ST-1227202292r61123E3CCB49081665" with session id "BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo\nSGFzaHsABjoKQHVzZWR7AA==--3ac0dad26b5ba8bf00d4a6485f54f64cd01e94a4". 359 | Rendering advanced_example/my_account 360 | Completed in 0.06489 (15 reqs/sec) | Rendering: 0.00154 (2%) | 200 OK [http://localhost/advanced_example/my_account?ticket=ST-1227202292r61123E3CCB49081665] 361 | 362 | 363 | Processing SimpleExampleController#index (for 127.0.0.1 at 2008-11-20 12:31:38) [GET] 364 | Session ID: BAh7CjoaY2FzX2xhc3RfdmFsaWRfdGlja2V0bzodQ0FTQ2xpZW50OjpTZXJ2 365 | aWNlVGlja2V0CToLQHJlbmV3MDoOQHJlc3BvbnNlbzoiQ0FTQ2xpZW50OjpW 366 | YWxpZGF0aW9uUmVzcG9uc2UKOgpAdXNlciIObXp1a293c2tpOhZAZXh0cmFf 367 | YXR0cmlidXRlc3sHIgdjbiISTWF0dCBadWtvd3NraSIJbWFpbCIabXp1a293 368 | c2tpQHVyYmFjb24ubmV0OhRAcGFyc2VfZGF0ZXRpbWVJdToJVGltZQ2RKhuA 369 | ua4CfgY6H0BtYXJzaGFsX3dpdGhfdXRjX2NvZXJjaW9uRjoJQHhtbG86E1JF 370 | WE1MOjpFbGVtZW50DToMQHByZWZpeCIIY2FzOg5AZWxlbWVudHNvOhRSRVhN 371 | TDo6RWxlbWVudHMGOg1AZWxlbWVudEAPOhBAYXR0cmlidXRlc0lDOhZSRVhN 372 | TDo6QXR0cmlidXRlc3sABjsUQA86E0BleHBhbmRlZF9uYW1lIh5jYXM6YXV0 373 | aGVudGljYXRpb25TdWNjZXNzOg5AY2hpbGRyZW5bCG87EA87ESIIY2FzOxJv 374 | OxMGOxRAFTodQGlnbm9yZV93aGl0ZXNwYWNlX25vZGVzRjsVSUM7FnsABjsU 375 | QBU6EEB3aGl0ZXNwYWNlVDsXIg1jYXM6dXNlcjsYWwZvOhBSRVhNTDo6VGV4 376 | dAs6EkB1bm5vcm1hbGl6ZWQiDm16dWtvd3NraToMQHN0cmluZyIObXp1a293 377 | c2tpOhBAbm9ybWFsaXplZDA6E0BlbnRpdHlfZmlsdGVyMDoJQHJhd1Q6DEBw 378 | YXJlbnRAFToNQGNvbnRleHR7ADoKQG5hbWUiCXVzZXI7IUAPbzsQEDsRIgA7 379 | Em87EwY7FEAgOxlGOxVJQzsWewAGOxRAIDsaVDsXIgdjbjsYWwZvOxsLOxww 380 | Ox0iEk1hdHQgWnVrb3dza2k7HjA7HzA7IFQ7IUAgOyJAHjsjIgdjbjoPQG5h 381 | bWVzcGFjZSIAOyFAD287EBA7ESIAOxJvOxMGOxRAKjsZRjsVSUM7FnsABjsU 382 | QCo7GlQ7FyIJbWFpbDsYWwZvOxsLOxwwOx0iGm16dWtvd3NraUB1cmJhY29u 383 | Lm5ldDseMDsfMDsgVDshQCo7IkAeOyMiCW1haWw7JCIAOyFADzsiQB47IyIa 384 | YXV0aGVudGljYXRpb25TdWNjZXNzOyFvOxANOxEiCGNhczsSbzsTBjsUQDU7 385 | FUlDOxZ7BiIIY2FzbzoVUkVYTUw6OkF0dHJpYnV0ZQw7ESIKeG1sbnM7FEA1 386 | OgtAdmFsdWUiH2h0dHA6Ly93d3cueWFsZS5lZHUvdHAvY2FzOxwiH2h0dHA6 387 | Ly93d3cueWFsZS5lZHUvdHAvY2FzOxciDnhtbG5zOmNhczseMDsjIghjYXMG 388 | OxRANTsXIhhjYXM6c2VydmljZVJlc3BvbnNlOxhbBkAPOyJAHjsjIhRzZXJ2 389 | aWNlUmVzcG9uc2U7IW86FFJFWE1MOjpEb2N1bWVudA47ESIAOxJvOxMGOxRA 390 | QzsVSUM7FnsABjsUQEM7FyIOVU5ERUZJTkVEOxhbBkA1OyJAHjsjIg5VTkRF 391 | RklORUQ7JCIAOyEwOg5AcHJvdG9jb2xmBjI6DUBzZXJ2aWNlIjZodHRwOi8v 392 | bG9jYWxob3N0OjMwMDAvYWR2YW5jZWRfZXhhbXBsZS9teV9hY2NvdW50OgxA 393 | dGlja2V0IiVTVC0xMjI3MjAyMjkycjYxMTIzRTNDQ0I0OTA4MTY2NToSY2Fz 394 | ZmlsdGVydXNlckAIOg1jYXNfdXNlciIObXp1a293c2tpIgpmbGFzaElDOidB 395 | Y3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA 396 | OhljYXNfZXh0cmFfYXR0cmlidXRlc0M6Hkhhc2hXaXRoSW5kaWZmZXJlbnRB 397 | Y2Nlc3N7B0AKQAtADEAN--e09693932a713df8635d9d1bd844b67e5406b0b0 398 | Parameters: {"action"=>"index", "controller"=>"simple_example"} 399 | Existing local CAS session detected for "mzukowski". Previous ticket "ST-1227202292r61123E3CCB49081665" will be re-used. 400 | Rendering simple_example/index 401 | Completed in 0.00278 (359 reqs/sec) | Rendering: 0.00116 (41%) | 200 OK [http://localhost/] 402 | 403 | 404 | Processing SimpleExampleController#logout (for 127.0.0.1 at 2008-11-20 12:31:40) [GET] 405 | Session ID: BAh7CjoaY2FzX2xhc3RfdmFsaWRfdGlja2V0bzodQ0FTQ2xpZW50OjpTZXJ2 406 | aWNlVGlja2V0CToLQHJlbmV3MDoNQHNlcnZpY2UiNmh0dHA6Ly9sb2NhbGhv 407 | c3Q6MzAwMC9hZHZhbmNlZF9leGFtcGxlL215X2FjY291bnQ6DkByZXNwb25z 408 | ZW86IkNBU0NsaWVudDo6VmFsaWRhdGlvblJlc3BvbnNlCjoKQHVzZXIiDm16 409 | dWtvd3NraToWQGV4dHJhX2F0dHJpYnV0ZXN7ByIHY24iEk1hdHQgWnVrb3dz 410 | a2kiCW1haWwiGm16dWtvd3NraUB1cmJhY29uLm5ldDoUQHBhcnNlX2RhdGV0 411 | aW1lSXU6CVRpbWUNkSobgLmuAn4GOh9AbWFyc2hhbF93aXRoX3V0Y19jb2Vy 412 | Y2lvbkY6CUB4bWxvOhNSRVhNTDo6RWxlbWVudA06DEBwcmVmaXgiCGNhczoO 413 | QGVsZW1lbnRzbzoUUkVYTUw6OkVsZW1lbnRzBjoNQGVsZW1lbnRAEDoQQGF0 414 | dHJpYnV0ZXNJQzoWUkVYTUw6OkF0dHJpYnV0ZXN7AAY7FUAQOhNAZXhwYW5k 415 | ZWRfbmFtZSIeY2FzOmF1dGhlbnRpY2F0aW9uU3VjY2VzczoOQGNoaWxkcmVu 416 | WwhvOxEPOxIiCGNhczsTbzsUBjsVQBY7FklDOxd7AAY7FUAWOh1AaWdub3Jl 417 | X3doaXRlc3BhY2Vfbm9kZXNGOhBAd2hpdGVzcGFjZVQ7GCINY2FzOnVzZXI7 418 | GVsGbzoQUkVYTUw6OlRleHQLOhJAdW5ub3JtYWxpemVkIg5tenVrb3dza2k6 419 | DEBzdHJpbmciDm16dWtvd3NraToQQG5vcm1hbGl6ZWQwOglAcmF3VDoTQGVu 420 | dGl0eV9maWx0ZXIwOgxAcGFyZW50QBY6DUBjb250ZXh0ewA6CkBuYW1lIgl1 421 | c2VyOyJAEG87ERA7EiIAOxNvOxQGOxVAITsWSUM7F3sABjsVQCE7GkY7G1Q7 422 | GCIHY247GVsGbzscCzsdMDseIhJNYXR0IFp1a293c2tpOx8wOyBUOyEwOyJA 423 | ITsjQB86D0BuYW1lc3BhY2UiADskIgdjbjsiQBBvOxEQOxIiADsTbzsUBjsV 424 | QCs7FklDOxd7AAY7FUArOxpGOxtUOxgiCW1haWw7GVsGbzscCzsdMDseIhpt 425 | enVrb3dza2lAdXJiYWNvbi5uZXQ7HzA7IFQ7ITA7IkArOyNAHzslIgA7JCIJ 426 | bWFpbDsiQBA7I0AfOyQiGmF1dGhlbnRpY2F0aW9uU3VjY2VzczsibzsRDTsS 427 | IghjYXM7E287FAY7FUA2OxZJQzsXewYiCGNhc286FVJFWE1MOjpBdHRyaWJ1 428 | dGUMOxVANjsSIgp4bWxuczoLQHZhbHVlIh9odHRwOi8vd3d3LnlhbGUuZWR1 429 | L3RwL2NhczsdIh9odHRwOi8vd3d3LnlhbGUuZWR1L3RwL2NhczsYIg54bWxu 430 | czpjYXM7HzA7JCIIY2FzBjsVQDY7GCIYY2FzOnNlcnZpY2VSZXNwb25zZTsZ 431 | WwZAEDsjQB87JCIUc2VydmljZVJlc3BvbnNlOyJvOhRSRVhNTDo6RG9jdW1l 432 | bnQOOxIiADsTbzsUBjsVQEQ7FklDOxd7AAY7FUBEOxgiDlVOREVGSU5FRDsZ 433 | WwZANjsjQB87JSIAOyQiDlVOREVGSU5FRDsiMDoOQHByb3RvY29sZgYyOgxA 434 | dGlja2V0IiVTVC0xMjI3MjAyMjkycjYxMTIzRTNDQ0I0OTA4MTY2NToSY2Fz 435 | ZmlsdGVydXNlckAJOg1jYXNfdXNlciIObXp1a293c2tpIgpmbGFzaElDOidB 436 | Y3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA 437 | OhljYXNfZXh0cmFfYXR0cmlidXRlc0M6Hkhhc2hXaXRoSW5kaWZmZXJlbnRB 438 | Y2Nlc3N7B0ALQAxADUAO--05ed2abdb70dda36ad8c307bdb9a18dd2d28884a 439 | Parameters: {"action"=>"logout", "controller"=>"simple_example"} 440 | Existing local CAS session detected for "mzukowski". Previous ticket "ST-1227202292r61123E3CCB49081665" will be re-used. 441 | Redirected to https://mzukowski.urbacon.net:6543/cas/logout?destination=http%3A%2F%2Flocalhost%3A3000%2F 442 | Completed in 0.02304 (43 reqs/sec) | 302 Found [http://localhost/simple_example/logout] 443 | 444 | 445 | Processing AdvancedExampleController#my_account (for 127.0.0.1 at 2008-11-20 12:31:40) [POST] 446 | Session ID: 22b93e12d13c98d3d7602555f4bc5db0 447 | Parameters: {"action"=>"my_account", "logoutRequest"=>"\n\nST-1227202292r61123E3CCB49081665\n", "controller"=>"advanced_example"} 448 | Intercepted single-sign-out request for CAS session "ST-1227202292r61123E3CCB49081665". 449 | 450 | 451 | NameError (uninitialized constant CGI::Session::ActiveRecordStore): 452 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:493:in `const_missing' 453 | /usr/lib/ruby/gems/1.8/gems/rubycas-client-2.0.99/lib/casclient/frameworks/rails/filter.rb:199:in `single_sign_out' 454 | /usr/lib/ruby/gems/1.8/gems/rubycas-client-2.0.99/lib/casclient/frameworks/rails/filter.rb:18:in `filter' 455 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/callbacks.rb:180:in `send' 456 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/callbacks.rb:180:in `evaluate_method' 457 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/callbacks.rb:161:in `call' 458 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:191:in `call' 459 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:591:in `run_before_filters' 460 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:577:in `call_filters' 461 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:572:in `perform_action_without_benchmark' 462 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 463 | /usr/lib/ruby/1.8/benchmark.rb:293:in `measure' 464 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 465 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/rescue.rb:201:in `perform_action' 466 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `send' 467 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `process_without_filters' 468 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:568:in `process_without_session_management_support' 469 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/session_management.rb:130:in `process' 470 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:389:in `process' 471 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:149:in `handle_request' 472 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:107:in `dispatch' 473 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `synchronize' 474 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `dispatch' 475 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:120:in `dispatch_cgi' 476 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:35:in `dispatch' 477 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:76:in `process' 478 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `synchronize' 479 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `process' 480 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:159:in `process_client' 481 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `each' 482 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `process_client' 483 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 484 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `initialize' 485 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `new' 486 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 487 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `initialize' 488 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `new' 489 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `run' 490 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:282:in `run' 491 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `each' 492 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `run' 493 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:128:in `run' 494 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/command.rb:212:in `run' 495 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:281 496 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 497 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 498 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 499 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 500 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/servers/mongrel.rb:64 501 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 502 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 503 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 504 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 505 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 506 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/server.rb:39 507 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 508 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 509 | script/server:3 510 | 511 | Rendering /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/templates/rescues/layout.erb (internal_server_error) 512 | 513 | 514 | Processing SimpleExampleController#index (for 127.0.0.1 at 2008-11-20 12:31:48) [GET] 515 | Session ID: BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo 516 | SGFzaHsABjoKQHVzZWR7AA==--3ac0dad26b5ba8bf00d4a6485f54f64cd01e94a4 517 | Parameters: {"action"=>"index", "controller"=>"simple_example"} 518 | Guessed service url: "http://localhost:3000/" 519 | Redirecting to "https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2F" 520 | Redirected to https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2F 521 | Filter chain halted as [CASClient::Frameworks::Rails::Filter] rendered_or_redirected. 522 | Completed in 0.00076 (1322 reqs/sec) | 302 Found [http://localhost/] 523 | 524 | 525 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:32:25) [GET] 526 | Session ID: BAh7CToYY2FzX3NlbnRfdG9fZ2F0ZXdheUY6HXByZXZpb3VzX3JlZGlyZWN0 527 | X3RvX2Nhc0l1OglUaW1lDZEqG4AAdAF/BjofQG1hcnNoYWxfd2l0aF91dGNf 528 | Y29lcmNpb25GOh9jYXNfdmFsaWRhdGlvbl9yZXRyeV9jb3VudGkAIgpmbGFz 529 | aElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA 530 | dXNlZHsA--06eb7b8f984114f478515d7f7bafc48a6c584e9b 531 | Parameters: {"action"=>"index", "controller"=>"advanced_example"} 532 | Guessed service url: "http://localhost:3000/advanced_example" 533 | Redirecting to "https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example&gateway=true" 534 | Redirected to https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example&gateway=true 535 | Filter chain halted as [CASClient::Frameworks::Rails::GatewayFilter] rendered_or_redirected. 536 | Completed in 0.00068 (1459 reqs/sec) | 302 Found [http://localhost/advanced_example/] 537 | 538 | 539 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:32:25) [GET] 540 | Session ID: BAh7CToYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0 541 | X3RvX2Nhc0l1OglUaW1lDZEqG4Ah0piBBjofQG1hcnNoYWxfd2l0aF91dGNf 542 | Y29lcmNpb25GOh9jYXNfdmFsaWRhdGlvbl9yZXRyeV9jb3VudGkAIgpmbGFz 543 | aElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA 544 | dXNlZHsA--d884e6ed45ef09f8cb038d5e0290d264b2765d54 545 | Parameters: {"action"=>"index", "controller"=>"advanced_example"} 546 | Returning from CAS gateway without authentication. 547 | This CAS client is configured to use gatewaying, so we will permit the user to continue without authentication. 548 | Rendering advanced_example/index 549 | Completed in 0.00303 (330 reqs/sec) | Rendering: 0.00127 (42%) | 200 OK [http://localhost/advanced_example] 550 | 551 | 552 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:32:46) [GET] 553 | Session ID: BAh7CToYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0 554 | X3RvX2Nhc0l1OglUaW1lDZEqG4Ah0piBBjofQG1hcnNoYWxfd2l0aF91dGNf 555 | Y29lcmNpb25GOh9jYXNfdmFsaWRhdGlvbl9yZXRyeV9jb3VudGkAIgpmbGFz 556 | aElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA 557 | dXNlZHsA--d884e6ed45ef09f8cb038d5e0290d264b2765d54 558 | Parameters: {"action"=>"index", "controller"=>"advanced_example"} 559 | Returning from CAS gateway without authentication. 560 | This CAS client is configured to use gatewaying, so we will permit the user to continue without authentication. 561 | Rendering advanced_example/index 562 | Completed in 0.00305 (327 reqs/sec) | Rendering: 0.00128 (41%) | 200 OK [http://localhost/advanced_example] 563 | 564 | 565 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:38:42) [GET] 566 | Session ID: BAh7CToYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0 567 | X3RvX2Nhc0l1OglUaW1lDZEqG4Ah0piBBjofQG1hcnNoYWxfd2l0aF91dGNf 568 | Y29lcmNpb25GOh9jYXNfdmFsaWRhdGlvbl9yZXRyeV9jb3VudGkAIgpmbGFz 569 | aElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA 570 | dXNlZHsA--d884e6ed45ef09f8cb038d5e0290d264b2765d54 571 | Parameters: {"action"=>"index", "controller"=>"advanced_example"} 572 | Returning from CAS gateway without authentication. 573 | This CAS client is configured to use gatewaying, so we will permit the user to continue without authentication. 574 | 575 | 576 | NoMethodError (undefined method `login_url' for CASClient::Frameworks::Rails::Filter:Class): 577 | /app/controllers/advanced_example_controller.rb:15:in `index' 578 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:1166:in `send' 579 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:1166:in `perform_action_without_filters' 580 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:579:in `call_filters' 581 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:572:in `perform_action_without_benchmark' 582 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 583 | /usr/lib/ruby/1.8/benchmark.rb:293:in `measure' 584 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 585 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/rescue.rb:201:in `perform_action' 586 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `send' 587 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `process_without_filters' 588 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:568:in `process_without_session_management_support' 589 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/session_management.rb:130:in `process' 590 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:389:in `process' 591 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:149:in `handle_request' 592 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:107:in `dispatch' 593 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `synchronize' 594 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `dispatch' 595 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:120:in `dispatch_cgi' 596 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:35:in `dispatch' 597 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:76:in `process' 598 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `synchronize' 599 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `process' 600 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:159:in `process_client' 601 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `each' 602 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `process_client' 603 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 604 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `initialize' 605 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `new' 606 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 607 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `initialize' 608 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `new' 609 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `run' 610 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:282:in `run' 611 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `each' 612 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `run' 613 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:128:in `run' 614 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/command.rb:212:in `run' 615 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:281 616 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 617 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 618 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 619 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 620 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/servers/mongrel.rb:64 621 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 622 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 623 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 624 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 625 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 626 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/server.rb:39 627 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 628 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 629 | script/server:3 630 | 631 | Rendering /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/templates/rescues/layout.erb (internal_server_error) 632 | 633 | 634 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:38:49) [GET] 635 | Session ID: BAh7CToYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0 636 | X3RvX2Nhc0l1OglUaW1lDZEqG4Ah0piBBjofQG1hcnNoYWxfd2l0aF91dGNf 637 | Y29lcmNpb25GOh9jYXNfdmFsaWRhdGlvbl9yZXRyeV9jb3VudGkAIgpmbGFz 638 | aElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA 639 | dXNlZHsA--d884e6ed45ef09f8cb038d5e0290d264b2765d54 640 | Parameters: {"action"=>"index", "controller"=>"advanced_example"} 641 | Returning from CAS gateway without authentication. 642 | This CAS client is configured to use gatewaying, so we will permit the user to continue without authentication. 643 | 644 | 645 | NoMethodError (undefined method `login_url' for CASClient::Frameworks::Rails::Filter:Class): 646 | /app/controllers/advanced_example_controller.rb:15:in `index' 647 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:1166:in `send' 648 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:1166:in `perform_action_without_filters' 649 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:579:in `call_filters' 650 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:572:in `perform_action_without_benchmark' 651 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 652 | /usr/lib/ruby/1.8/benchmark.rb:293:in `measure' 653 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 654 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/rescue.rb:201:in `perform_action' 655 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `send' 656 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `process_without_filters' 657 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:568:in `process_without_session_management_support' 658 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/session_management.rb:130:in `process' 659 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:389:in `process' 660 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:149:in `handle_request' 661 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:107:in `dispatch' 662 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `synchronize' 663 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `dispatch' 664 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:120:in `dispatch_cgi' 665 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:35:in `dispatch' 666 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:76:in `process' 667 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `synchronize' 668 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `process' 669 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:159:in `process_client' 670 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `each' 671 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `process_client' 672 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 673 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `initialize' 674 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `new' 675 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 676 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `initialize' 677 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `new' 678 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `run' 679 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:282:in `run' 680 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `each' 681 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `run' 682 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:128:in `run' 683 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/command.rb:212:in `run' 684 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:281 685 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 686 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 687 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 688 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 689 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/servers/mongrel.rb:64 690 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 691 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 692 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 693 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 694 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 695 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/server.rb:39 696 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 697 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 698 | script/server:3 699 | 700 | Rendering /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/templates/rescues/layout.erb (internal_server_error) 701 | 702 | 703 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:38:51) [GET] 704 | Session ID: BAh7CToYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0 705 | X3RvX2Nhc0l1OglUaW1lDZEqG4Ah0piBBjofQG1hcnNoYWxfd2l0aF91dGNf 706 | Y29lcmNpb25GOh9jYXNfdmFsaWRhdGlvbl9yZXRyeV9jb3VudGkAIgpmbGFz 707 | aElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA 708 | dXNlZHsA--d884e6ed45ef09f8cb038d5e0290d264b2765d54 709 | Parameters: {"action"=>"index", "controller"=>"advanced_example"} 710 | Returning from CAS gateway without authentication. 711 | This CAS client is configured to use gatewaying, so we will permit the user to continue without authentication. 712 | 713 | 714 | NoMethodError (undefined method `login_url' for CASClient::Frameworks::Rails::Filter:Class): 715 | /app/controllers/advanced_example_controller.rb:15:in `index' 716 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:1166:in `send' 717 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:1166:in `perform_action_without_filters' 718 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:579:in `call_filters' 719 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:572:in `perform_action_without_benchmark' 720 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 721 | /usr/lib/ruby/1.8/benchmark.rb:293:in `measure' 722 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 723 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/rescue.rb:201:in `perform_action' 724 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `send' 725 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:529:in `process_without_filters' 726 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/filters.rb:568:in `process_without_session_management_support' 727 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/session_management.rb:130:in `process' 728 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/base.rb:389:in `process' 729 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:149:in `handle_request' 730 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:107:in `dispatch' 731 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `synchronize' 732 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:104:in `dispatch' 733 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:120:in `dispatch_cgi' 734 | /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/dispatcher.rb:35:in `dispatch' 735 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:76:in `process' 736 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `synchronize' 737 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/../lib/mongrel/rails.rb:74:in `process' 738 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:159:in `process_client' 739 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `each' 740 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `process_client' 741 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 742 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `initialize' 743 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `new' 744 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run' 745 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `initialize' 746 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `new' 747 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `run' 748 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:282:in `run' 749 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `each' 750 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `run' 751 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:128:in `run' 752 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/command.rb:212:in `run' 753 | /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:281 754 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 755 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 756 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 757 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:503:in `load' 758 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/servers/mongrel.rb:64 759 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 760 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 761 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 762 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:355:in `new_constants_in' 763 | /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:510:in `require' 764 | /usr/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/server.rb:39 765 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 766 | /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 767 | script/server:3 768 | 769 | Rendering /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.2/lib/action_controller/templates/rescues/layout.erb (internal_server_error) 770 | 771 | 772 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:39:28) [GET] 773 | Session ID: BAh7CToYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0 774 | X3RvX2Nhc0l1OglUaW1lDZEqG4Ah0piBBjofQG1hcnNoYWxfd2l0aF91dGNf 775 | Y29lcmNpb25GOh9jYXNfdmFsaWRhdGlvbl9yZXRyeV9jb3VudGkAIgpmbGFz 776 | aElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA 777 | dXNlZHsA--d884e6ed45ef09f8cb038d5e0290d264b2765d54 778 | Parameters: {"action"=>"index", "controller"=>"advanced_example"} 779 | Returning from CAS gateway without authentication. 780 | This CAS client is configured to use gatewaying, so we will permit the user to continue without authentication. 781 | Guessed service url: "http://localhost:3000/advanced_example" 782 | Generated login url: https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example 783 | Rendering advanced_example/index 784 | Completed in 0.00380 (263 reqs/sec) | Rendering: 0.00124 (32%) | 200 OK [http://localhost/advanced_example] 785 | 786 | 787 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:39:38) [GET] 788 | Session ID: BAh7CToYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0 789 | X3RvX2Nhc0l1OglUaW1lDZEqG4Ah0piBBjofQG1hcnNoYWxfd2l0aF91dGNf 790 | Y29lcmNpb25GOh9jYXNfdmFsaWRhdGlvbl9yZXRyeV9jb3VudGkAIgpmbGFz 791 | aElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA 792 | dXNlZHsA--d884e6ed45ef09f8cb038d5e0290d264b2765d54 793 | Parameters: {"ticket"=>"ST-1227202778r635C166263A75DC7C1", "action"=>"index", "controller"=>"advanced_example"} 794 | Request contains ticket "ST-1227202778r635C166263A75DC7C1". 795 | Guessed service url: "http://localhost:3000/advanced_example" 796 | Requesting CAS response for URI https://mzukowski.urbacon.net:6543/cas/proxyValidate?ticket=ST-1227202778r635C166263A75DC7C1&service=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example 797 | CAS server responded with #: 798 | mzukowskiMatt Zukowskimzukowski@urbacon.net 799 | Ticket "ST-1227202778r635C166263A75DC7C1" for service "http://localhost:3000/advanced_example" belonging to user "mzukowski" is VALID. 800 | Extra user attributes provided along with ticket "ST-1227202778r635C166263A75DC7C1": {"cn"=>"Matt Zukowski", "mail"=>"mzukowski@urbacon.net"}. 801 | Wrote service session lookup file to "/home/URBACON/mzukowski/workspace/rubycas-client2/examples/rails/tmp/sessions/cas_sess.ST-1227202778r635C166263A75DC7C1" with session id "BAh7CToYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0\nX3RvX2Nhc0l1OglUaW1lDZEqG4Ah0piBBjofQG1hcnNoYWxfd2l0aF91dGNf\nY29lcmNpb25GOh9jYXNfdmFsaWRhdGlvbl9yZXRyeV9jb3VudGkAIgpmbGFz\naElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpA\ndXNlZHsA--d884e6ed45ef09f8cb038d5e0290d264b2765d54". 802 | Guessed service url: "http://localhost:3000/advanced_example" 803 | Generated login url: https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example 804 | Rendering advanced_example/index 805 | Completed in 0.02237 (44 reqs/sec) | Rendering: 0.00058 (2%) | 200 OK [http://localhost/advanced_example?ticket=ST-1227202778r635C166263A75DC7C1] 806 | 807 | 808 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:47:00) [GET] 809 | Session ID: BAh7DToaY2FzX2xhc3RfdmFsaWRfdGlja2V0bzodQ0FTQ2xpZW50OjpTZXJ2 810 | aWNlVGlja2V0CToLQHJlbmV3MDoOQHJlc3BvbnNlbzoiQ0FTQ2xpZW50OjpW 811 | YWxpZGF0aW9uUmVzcG9uc2UKOgpAdXNlciIObXp1a293c2tpOhZAZXh0cmFf 812 | YXR0cmlidXRlc3sHIgdjbiISTWF0dCBadWtvd3NraSIJbWFpbCIabXp1a293 813 | c2tpQHVyYmFjb24ubmV0OhRAcGFyc2VfZGF0ZXRpbWVJdToJVGltZQ2RKhuA 814 | mKhungY6H0BtYXJzaGFsX3dpdGhfdXRjX2NvZXJjaW9uRjoJQHhtbG86E1JF 815 | WE1MOjpFbGVtZW50DToMQHByZWZpeCIIY2FzOg5AZWxlbWVudHNvOhRSRVhN 816 | TDo6RWxlbWVudHMGOg1AZWxlbWVudEAPOhBAYXR0cmlidXRlc0lDOhZSRVhN 817 | TDo6QXR0cmlidXRlc3sABjsUQA86E0BleHBhbmRlZF9uYW1lIh5jYXM6YXV0 818 | aGVudGljYXRpb25TdWNjZXNzOg5AY2hpbGRyZW5bCG87EA87ESIIY2FzOxJv 819 | OxMGOxRAFTodQGlnbm9yZV93aGl0ZXNwYWNlX25vZGVzRjsVSUM7FnsABjsU 820 | QBU6EEB3aGl0ZXNwYWNlVDsXIg1jYXM6dXNlcjsYWwZvOhBSRVhNTDo6VGV4 821 | dAs6EkB1bm5vcm1hbGl6ZWQiDm16dWtvd3NraToMQHN0cmluZyIObXp1a293 822 | c2tpOhBAbm9ybWFsaXplZDA6E0BlbnRpdHlfZmlsdGVyMDoJQHJhd1Q6DEBw 823 | YXJlbnRAFToNQGNvbnRleHR7ADoKQG5hbWUiCXVzZXI7IUAPbzsQEDsRIgA7 824 | Em87EwY7FEAgOxlGOxVJQzsWewAGOxRAIDsaVDsXIgdjbjsYWwZvOxsLOxww 825 | Ox0iEk1hdHQgWnVrb3dza2k7HjA7HzA7IFQ7IUAgOyJAHjsjIgdjbjoPQG5h 826 | bWVzcGFjZSIAOyFAD287EBA7ESIAOxJvOxMGOxRAKjsZRjsVSUM7FnsABjsU 827 | QCo7GlQ7FyIJbWFpbDsYWwZvOxsLOxwwOx0iGm16dWtvd3NraUB1cmJhY29u 828 | Lm5ldDseMDsfMDsgVDshQCo7IkAeOyMiCW1haWw7JCIAOyFADzsiQB47IyIa 829 | YXV0aGVudGljYXRpb25TdWNjZXNzOyFvOxANOxEiCGNhczsSbzsTBjsUQDU7 830 | FUlDOxZ7BiIIY2FzbzoVUkVYTUw6OkF0dHJpYnV0ZQw7ESIKeG1sbnM7FEA1 831 | OgtAdmFsdWUiH2h0dHA6Ly93d3cueWFsZS5lZHUvdHAvY2FzOxwiH2h0dHA6 832 | Ly93d3cueWFsZS5lZHUvdHAvY2FzOxciDnhtbG5zOmNhczseMDsjIghjYXMG 833 | OxRANTsXIhhjYXM6c2VydmljZVJlc3BvbnNlOxhbBkAPOyJAHjsjIhRzZXJ2 834 | aWNlUmVzcG9uc2U7IW86FFJFWE1MOjpEb2N1bWVudA47ESIAOxJvOxMGOxRA 835 | QzsVSUM7FnsABjsUQEM7FyIOVU5ERUZJTkVEOxhbBkA1OyJAHjsjIg5VTkRF 836 | RklORUQ7JCIAOyEwOg5AcHJvdG9jb2xmBjI6DUBzZXJ2aWNlIitodHRwOi8v 837 | bG9jYWxob3N0OjMwMDAvYWR2YW5jZWRfZXhhbXBsZToMQHRpY2tldCIlU1Qt 838 | MTIyNzIwMjc3OHI2MzVDMTY2MjYzQTc1REM3QzE6EmNhc2ZpbHRlcnVzZXJA 839 | CDoYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0X3Rv 840 | X2Nhc0l1Ow0NkSobgCHSmIEGOw5GOg1jYXNfdXNlciIObXp1a293c2tpOh9j 841 | YXNfdmFsaWRhdGlvbl9yZXRyeV9jb3VudGkAIgpmbGFzaElDOidBY3Rpb25D 842 | b250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsAOhljYXNf 843 | ZXh0cmFfYXR0cmlidXRlc0M6Hkhhc2hXaXRoSW5kaWZmZXJlbnRBY2Nlc3N7 844 | B0AKQAtADEAN--c3c095f05414d41aeebb5c6cd3630f3995da698e 845 | Parameters: {"ticket"=>"ST-1227202778r635C166263A75DC7C1", "action"=>"index", "controller"=>"advanced_example"} 846 | Request contains ticket "ST-1227202778r635C166263A75DC7C1". 847 | Guessed service url: "http://localhost:3000/advanced_example" 848 | Re-using previously validated ticket since the ticket id and service are the same. 849 | Guessed service url: "http://localhost:3000/advanced_example" 850 | Generated login url: https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example 851 | Rendering advanced_example/index 852 | Completed in 0.00501 (199 reqs/sec) | Rendering: 0.00194 (38%) | 200 OK [http://localhost/advanced_example?ticket=ST-1227202778r635C166263A75DC7C1] 853 | 854 | 855 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:48:47) [GET] 856 | Session ID: BAh7DToYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0 857 | X3RvX2Nhc0l1OglUaW1lDZEqG4Ah0piBBjofQG1hcnNoYWxfd2l0aF91dGNf 858 | Y29lcmNpb25GOg1jYXNfdXNlciIObXp1a293c2tpOh9jYXNfdmFsaWRhdGlv 859 | bl9yZXRyeV9jb3VudGkAOhljYXNfZXh0cmFfYXR0cmlidXRlc0M6Hkhhc2hX 860 | aXRoSW5kaWZmZXJlbnRBY2Nlc3N7ByIHY24iEk1hdHQgWnVrb3dza2kiCW1h 861 | aWwiGm16dWtvd3NraUB1cmJhY29uLm5ldCIKZmxhc2hJQzonQWN0aW9uQ29u 862 | dHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7ADoaY2FzX2xh 863 | c3RfdmFsaWRfdGlja2V0bzodQ0FTQ2xpZW50OjpTZXJ2aWNlVGlja2V0CToO 864 | QHJlc3BvbnNlbzoiQ0FTQ2xpZW50OjpWYWxpZGF0aW9uUmVzcG9uc2UKOgpA 865 | dXNlciIObXp1a293c2tpOglAeG1sbzoTUkVYTUw6OkVsZW1lbnQNOgxAcHJl 866 | Zml4IghjYXM6DkBlbGVtZW50c286FFJFWE1MOjpFbGVtZW50cwY6DUBlbGVt 867 | ZW50QBM6EEBhdHRyaWJ1dGVzSUM6FlJFWE1MOjpBdHRyaWJ1dGVzewAGOxlA 868 | EzoTQGV4cGFuZGVkX25hbWUiHmNhczphdXRoZW50aWNhdGlvblN1Y2Nlc3M6 869 | DkBjaGlsZHJlblsIbzsVDzsWIghjYXM7F287GAY7GUAZOxpJQzsbewAGOxlA 870 | GTodQGlnbm9yZV93aGl0ZXNwYWNlX25vZGVzRjoQQHdoaXRlc3BhY2VUOxwi 871 | DWNhczp1c2VyOx1bBm86EFJFWE1MOjpUZXh0CzoSQHVubm9ybWFsaXplZCIO 872 | bXp1a293c2tpOgxAc3RyaW5nIg5tenVrb3dza2k6EEBub3JtYWxpemVkMDoJ 873 | QHJhd1Q6E0BlbnRpdHlfZmlsdGVyMDoMQHBhcmVudEAZOg1AY29udGV4dHsA 874 | OgpAbmFtZSIJdXNlcjsmQBNvOxUQOxYiADsXbzsYBjsZQCQ7GklDOxt7AAY7 875 | GUAkOx5GOx9UOxwiB2NuOx1bBm87IAs7ITA7IiISTWF0dCBadWtvd3NraTsj 876 | MDskVDslMDsmQCQ7J0AiOg9AbmFtZXNwYWNlIgA7KCIHY247JkATbzsVEDsW 877 | IgA7F287GAY7GUAuOxpJQzsbewAGOxlALjseRjsfVDscIgltYWlsOx1bBm87 878 | IAs7ITA7IiIabXp1a293c2tpQHVyYmFjb24ubmV0OyMwOyRUOyUwOyZALjsn 879 | QCI7KSIAOygiCW1haWw7JkATOydAIjsoIhphdXRoZW50aWNhdGlvblN1Y2Nl 880 | c3M7Jm87FQ07FiIIY2FzOxdvOxgGOxlAOTsaSUM7G3sGIghjYXNvOhVSRVhN 881 | TDo6QXR0cmlidXRlDDsZQDk7FiIKeG1sbnM6C0B2YWx1ZSIfaHR0cDovL3d3 882 | dy55YWxlLmVkdS90cC9jYXM7ISIfaHR0cDovL3d3dy55YWxlLmVkdS90cC9j 883 | YXM7HCIOeG1sbnM6Y2FzOyMwOygiCGNhcwY7GUA5OxwiGGNhczpzZXJ2aWNl 884 | UmVzcG9uc2U7HVsGQBM7J0AiOygiFHNlcnZpY2VSZXNwb25zZTsmbzoUUkVY 885 | TUw6OkRvY3VtZW50DjsWIgA7F287GAY7GUBHOxpJQzsbewAGOxlARzscIg5V 886 | TkRFRklORUQ7HVsGQDk7J0AiOykiADsoIg5VTkRFRklORUQ7JjA6FkBleHRy 887 | YV9hdHRyaWJ1dGVzewdACUAKQAtADDoOQHByb3RvY29sZgYyOhRAcGFyc2Vf 888 | ZGF0ZXRpbWVJdTsHDZEqG4CYqG6eBjsIRjoLQHJlbmV3MDoNQHNlcnZpY2Ui 889 | K2h0dHA6Ly9sb2NhbGhvc3Q6MzAwMC9hZHZhbmNlZF9leGFtcGxlOgxAdGlj 890 | a2V0IiVTVC0xMjI3MjAyNzc4cjYzNUMxNjYyNjNBNzVEQzdDMToSY2FzZmls 891 | dGVydXNlckAS--9d74601d600be2c4d5ece518aff1f040923892d8 892 | Parameters: {"ticket"=>"ST-1227202778r635C166263A75DC7C1", "action"=>"index", "controller"=>"advanced_example"} 893 | Request contains ticket "ST-1227202778r635C166263A75DC7C1". 894 | Guessed service url: "http://localhost:3000/advanced_example" 895 | Re-using previously validated ticket since the ticket id and service are the same. 896 | Guessed service url: "http://localhost:3000/advanced_example" 897 | Generated login url: https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example 898 | Rendering advanced_example/index 899 | Completed in 0.00383 (260 reqs/sec) | Rendering: 0.00132 (34%) | 200 OK [http://localhost/advanced_example?ticket=ST-1227202778r635C166263A75DC7C1] 900 | 901 | 902 | Processing AdvancedExampleController#index (for 127.0.0.1 at 2008-11-20 12:49:40) [GET] 903 | Session ID: BAh7DToYY2FzX3NlbnRfdG9fZ2F0ZXdheVQ6HXByZXZpb3VzX3JlZGlyZWN0 904 | X3RvX2Nhc0l1OglUaW1lDZEqG4Ah0piBBjofQG1hcnNoYWxfd2l0aF91dGNf 905 | Y29lcmNpb25GOg1jYXNfdXNlciIObXp1a293c2tpOh9jYXNfdmFsaWRhdGlv 906 | bl9yZXRyeV9jb3VudGkAOhljYXNfZXh0cmFfYXR0cmlidXRlc0M6Hkhhc2hX 907 | aXRoSW5kaWZmZXJlbnRBY2Nlc3N7ByIHY24iEk1hdHQgWnVrb3dza2kiCW1h 908 | aWwiGm16dWtvd3NraUB1cmJhY29uLm5ldDoaY2FzX2xhc3RfdmFsaWRfdGlj 909 | a2V0bzodQ0FTQ2xpZW50OjpTZXJ2aWNlVGlja2V0CToLQHJlbmV3MDoOQHJl 910 | c3BvbnNlbzoiQ0FTQ2xpZW50OjpWYWxpZGF0aW9uUmVzcG9uc2UKOgpAdXNl 911 | ciIObXp1a293c2tpOhZAZXh0cmFfYXR0cmlidXRlc3sHQAlACkALQAw6CUB4 912 | bWxvOhNSRVhNTDo6RWxlbWVudA06DEBwcmVmaXgiCGNhczoOQGVsZW1lbnRz 913 | bzoUUkVYTUw6OkVsZW1lbnRzBjoNQGVsZW1lbnRAEToQQGF0dHJpYnV0ZXNJ 914 | QzoWUkVYTUw6OkF0dHJpYnV0ZXN7AAY7GUAROhNAZXhwYW5kZWRfbmFtZSIe 915 | Y2FzOmF1dGhlbnRpY2F0aW9uU3VjY2VzczoOQGNoaWxkcmVuWwhvOxUPOxYi 916 | CGNhczsXbzsYBjsZQBc6HUBpZ25vcmVfd2hpdGVzcGFjZV9ub2Rlc0Y7GklD 917 | Oxt7AAY7GUAXOhBAd2hpdGVzcGFjZVQ7HCINY2FzOnVzZXI7HVsGbzoQUkVY 918 | TUw6OlRleHQLOhJAdW5ub3JtYWxpemVkIg5tenVrb3dza2k6DEBzdHJpbmci 919 | Dm16dWtvd3NraToQQG5vcm1hbGl6ZWQwOhNAZW50aXR5X2ZpbHRlcjA6CUBy 920 | YXdUOgxAcGFyZW50QBc6DUBjb250ZXh0ewA6CkBuYW1lIgl1c2VyOyZAEW87 921 | FRA7FiIAOxdvOxgGOxlAIjseRjsaSUM7G3sABjsZQCI7H1Q7HCIHY247HVsG 922 | bzsgCzshMDsiIhJNYXR0IFp1a293c2tpOyMwOyQwOyVUOyZAIjsnQCA7KCIH 923 | Y246D0BuYW1lc3BhY2UiADsmQBFvOxUQOxYiADsXbzsYBjsZQCw7HkY7GklD 924 | Oxt7AAY7GUAsOx9UOxwiCW1haWw7HVsGbzsgCzshMDsiIhptenVrb3dza2lA 925 | dXJiYWNvbi5uZXQ7IzA7JDA7JVQ7JkAsOydAIDsoIgltYWlsOykiADsmQBE7 926 | J0AgOygiGmF1dGhlbnRpY2F0aW9uU3VjY2VzczsmbzsVDTsWIghjYXM7F287 927 | GAY7GUA3OxpJQzsbewYiCGNhc286FVJFWE1MOjpBdHRyaWJ1dGUMOxYiCnht 928 | bG5zOxlANzoLQHZhbHVlIh9odHRwOi8vd3d3LnlhbGUuZWR1L3RwL2Nhczsh 929 | Ih9odHRwOi8vd3d3LnlhbGUuZWR1L3RwL2NhczscIg54bWxuczpjYXM7IzA7 930 | KCIIY2FzBjsZQDc7HCIYY2FzOnNlcnZpY2VSZXNwb25zZTsdWwZAETsnQCA7 931 | KCIUc2VydmljZVJlc3BvbnNlOyZvOhRSRVhNTDo6RG9jdW1lbnQOOxYiADsX 932 | bzsYBjsZQEU7GklDOxt7AAY7GUBFOxwiDlVOREVGSU5FRDsdWwZANzsnQCA7 933 | KCIOVU5ERUZJTkVEOykiADsmMDoUQHBhcnNlX2RhdGV0aW1lSXU7Bw2RKhuA 934 | mKhungY7CEY6DkBwcm90b2NvbGYGMjoNQHNlcnZpY2UiK2h0dHA6Ly9sb2Nh 935 | bGhvc3Q6MzAwMC9hZHZhbmNlZF9leGFtcGxlOgxAdGlja2V0IiVTVC0xMjI3 936 | MjAyNzc4cjYzNUMxNjYyNjNBNzVEQzdDMSIKZmxhc2hJQzonQWN0aW9uQ29u 937 | dHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7ADoSY2FzZmls 938 | dGVydXNlckAP--f6abd28027e3ebd81f1197903bf4266e4b3a7a16 939 | Parameters: {"ticket"=>"ST-1227202778r635C166263A75DC7C1", "action"=>"index", "controller"=>"advanced_example"} 940 | Request contains ticket "ST-1227202778r635C166263A75DC7C1". 941 | Guessed service url: "http://localhost:3000/advanced_example" 942 | Re-using previously validated ticket since the ticket id and service are the same. 943 | Guessed service url: "http://localhost:3000/advanced_example" 944 | Generated login url: https://mzukowski.urbacon.net:6543/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fadvanced_example 945 | Rendering advanced_example/index 946 | Completed in 0.00497 (201 reqs/sec) | Rendering: 0.00177 (35%) | 200 OK [http://localhost/advanced_example?ticket=ST-1227202778r635C166263A75DC7C1] 947 | -------------------------------------------------------------------------------- /examples/rails/log/production.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubycas/rubycas-client/7b67c8f1b5515ee4e28479d640d2da0a5aadfbe0/examples/rails/log/production.log -------------------------------------------------------------------------------- /examples/rails/log/server.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubycas/rubycas-client/7b67c8f1b5515ee4e28479d640d2da0a5aadfbe0/examples/rails/log/server.log -------------------------------------------------------------------------------- /examples/rails/log/test.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubycas/rubycas-client/7b67c8f1b5515ee4e28479d640d2da0a5aadfbe0/examples/rails/log/test.log -------------------------------------------------------------------------------- /examples/rails/script/about: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | $LOAD_PATH.unshift "#{RAILTIES_PATH}/builtin/rails_info" 4 | require 'commands/about' -------------------------------------------------------------------------------- /examples/rails/script/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/console' 4 | -------------------------------------------------------------------------------- /examples/rails/script/server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/server' 4 | -------------------------------------------------------------------------------- /gemfiles/.gitignore: -------------------------------------------------------------------------------- 1 | *.lock 2 | -------------------------------------------------------------------------------- /gemfiles/rails23.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://rubygems.org" 4 | 5 | gem "activesupport", "~> 2.3.11" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/rails30.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://rubygems.org" 4 | 5 | gem "rails", "~> 3.0.17" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/rails31.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://rubygems.org" 4 | 5 | gem "rails", "~> 3.1.8" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/rails32.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://rubygems.org" 4 | 5 | gem "rails", "~> 3.2.8" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /lib/casclient.rb: -------------------------------------------------------------------------------- 1 | require 'uri' 2 | require 'cgi' 3 | require 'logger' 4 | require 'net/https' 5 | require 'rexml/document' 6 | 7 | begin 8 | require 'active_support' 9 | rescue LoadError 10 | require 'rubygems' 11 | require 'active_support' 12 | end 13 | 14 | $: << File.expand_path(File.dirname(__FILE__)) 15 | 16 | module CASClient 17 | class CASException < Exception 18 | end 19 | 20 | # Customized logger for the client. 21 | # This is useful if you're trying to do logging in Rails, since Rails' 22 | # clean_logger.rb pretty much completely breaks the base Logger class. 23 | class Logger < ::Logger 24 | def initialize(logdev, shift_age = 0, shift_size = 1048576) 25 | @default_formatter = Formatter.new 26 | super 27 | end 28 | 29 | def format_message(severity, datetime, progrname, msg) 30 | (@formatter || @default_formatter).call(severity, datetime, progname, msg) 31 | end 32 | 33 | def break 34 | self << $/ 35 | end 36 | 37 | class Formatter < ::Logger::Formatter 38 | Format = "[%s#%d] %5s -- %s: %s\n" 39 | 40 | def call(severity, time, progname, msg) 41 | Format % [format_datetime(time), $$, severity, progname, msg2str(msg)] 42 | end 43 | end 44 | end 45 | 46 | # Wraps a real Logger. If no real Logger is set, then this wrapper 47 | # will quietly swallow any logging calls. 48 | class LoggerWrapper 49 | def initialize(real_logger=nil) 50 | set_logger(real_logger) 51 | end 52 | # Assign the 'real' Logger instance that this dummy instance wraps around. 53 | def set_real_logger(real_logger) 54 | @real_logger = real_logger 55 | end 56 | # Log using the appropriate method if we have a logger 57 | # if we dont' have a logger, gracefully ignore. 58 | def method_missing(name, *args) 59 | if !@real_logger.nil? && @real_logger.respond_to?(name) 60 | @real_logger.send(name, *args) 61 | end 62 | end 63 | end 64 | end 65 | 66 | require 'casclient/tickets' 67 | require 'casclient/responses' 68 | require 'casclient/client' 69 | require 'casclient/tickets/storage' 70 | autoload :ACTIVE_RECORD_TICKET_STORE, 'casclient/tickets/storage/active_record_ticket_store' 71 | if defined?(Rails) && defined?(ActionController::Base) 72 | require 'casclient/frameworks/rails/filter' 73 | require 'casclient/frameworks/rails/cas_proxy_callback_controller' 74 | end 75 | 76 | # Detect legacy configuration and show appropriate error message 77 | module CAS 78 | module Filter 79 | class << self 80 | def method_missing(method, *args) 81 | $stderr.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 82 | $stderr.puts 83 | $stderr.puts "WARNING: Your RubyCAS-Client configuration is no longer valid!!" 84 | $stderr.puts 85 | $stderr.puts "For information on the new configuration format please see: " 86 | $stderr.puts 87 | $stderr.puts " http://rubycas-client.googlecode.com/svn/trunk/rubycas-client/README.txt" 88 | $stderr.puts 89 | $stderr.puts "After upgrading your configuration you should also clear your application's session store." 90 | $stderr.puts 91 | $stderr.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 92 | end 93 | end 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /lib/casclient/client.rb: -------------------------------------------------------------------------------- 1 | module CASClient 2 | # The client brokers all HTTP transactions with the CAS server. 3 | class Client 4 | attr_reader :cas_base_url, :cas_destination_logout_param_name 5 | attr_reader :log, :username_session_key, :extra_attributes_session_key 6 | attr_reader :ticket_store 7 | attr_reader :proxy_host, :proxy_port 8 | attr_writer :login_url, :validate_url, :proxy_url, :logout_url, :service_url 9 | attr_accessor :proxy_callback_url, :proxy_retrieval_url 10 | 11 | def initialize(conf = nil) 12 | configure(conf) if conf 13 | end 14 | 15 | def configure(conf) 16 | #TODO: raise error if conf contains unrecognized cas options (this would help detect user typos in the config) 17 | 18 | raise ArgumentError, "Missing :cas_base_url parameter!" unless conf[:cas_base_url] 19 | 20 | if conf.has_key?("encode_extra_attributes_as") 21 | unless (conf[:encode_extra_attributes_as] == :json || conf[:encode_extra_attributes_as] == :yaml) 22 | raise ArgumentError, "Unkown Value for :encode_extra_attributes_as parameter! Allowed options are json or yaml - #{conf[:encode_extra_attributes_as]}" 23 | end 24 | end 25 | 26 | @cas_base_url = conf[:cas_base_url].gsub(/\/$/, '') 27 | @cas_destination_logout_param_name = conf[:cas_destination_logout_param_name] 28 | 29 | @login_url = conf[:login_url] 30 | @logout_url = conf[:logout_url] 31 | @validate_url = conf[:validate_url] 32 | @proxy_url = conf[:proxy_url] 33 | @service_url = conf[:service_url] 34 | @force_ssl_verification = conf[:force_ssl_verification] 35 | @proxy_callback_url = conf[:proxy_callback_url] 36 | 37 | #proxy server settings 38 | @proxy_host = conf[:proxy_host] 39 | @proxy_port = conf[:proxy_port] 40 | 41 | @username_session_key = conf[:username_session_key] || :cas_user 42 | @extra_attributes_session_key = conf[:extra_attributes_session_key] || :cas_extra_attributes 43 | @ticket_store_class = case conf[:ticket_store] 44 | when :local_dir_ticket_store, nil 45 | CASClient::Tickets::Storage::LocalDirTicketStore 46 | when :active_record_ticket_store 47 | require 'casclient/tickets/storage/active_record_ticket_store' 48 | CASClient::Tickets::Storage::ActiveRecordTicketStore 49 | else 50 | conf[:ticket_store] 51 | end 52 | @ticket_store = @ticket_store_class.new conf[:ticket_store_config] 53 | raise CASException, "The Ticket Store is not a subclass of AbstractTicketStore, it is a #{@ticket_store_class}" unless @ticket_store.kind_of? CASClient::Tickets::Storage::AbstractTicketStore 54 | 55 | @log = CASClient::LoggerWrapper.new 56 | @log.set_real_logger(conf[:logger]) if conf[:logger] 57 | @ticket_store.log = @log 58 | @conf_options = conf 59 | end 60 | 61 | def cas_destination_logout_param_name 62 | @cas_destination_logout_param_name || "destination" 63 | end 64 | 65 | def login_url 66 | @login_url || (cas_base_url + "/login") 67 | end 68 | 69 | def validate_url 70 | @validate_url || (cas_base_url + "/proxyValidate") 71 | end 72 | 73 | # Returns the CAS server's logout url. 74 | # 75 | # If a logout_url has not been explicitly configured, 76 | # the default is cas_base_url + "/logout". 77 | # 78 | # destination_url:: Set this if you want the user to be 79 | # able to immediately log back in. Generally 80 | # you'll want to use something like request.referer. 81 | # Note that the above behaviour describes RubyCAS-Server 82 | # -- other CAS server implementations might use this 83 | # parameter differently (or not at all). 84 | # follow_url:: This satisfies section 2.3.1 of the CAS protocol spec. 85 | # See http://www.ja-sig.org/products/cas/overview/protocol 86 | def logout_url(destination_url = nil, follow_url = nil, service_url = nil) 87 | url = @logout_url || (cas_base_url + "/logout") 88 | uri = URI.parse(url) 89 | service_url = (service_url if service_url) || @service_url 90 | h = uri.query ? query_to_hash(uri.query) : {} 91 | 92 | if destination_url 93 | # if present, remove the 'ticket' parameter from the destination_url 94 | duri = URI.parse(destination_url) 95 | dh = duri.query ? query_to_hash(duri.query) : {} 96 | dh.delete('ticket') 97 | duri.query = hash_to_query(dh) 98 | destination_url = duri.to_s.gsub(/\?$/, '') 99 | h[cas_destination_logout_param_name] = destination_url if destination_url 100 | h['gateway'] = 'true' 101 | elsif follow_url 102 | h['url'] = follow_url if follow_url 103 | h['service'] = service_url 104 | else 105 | h['service'] = service_url 106 | end 107 | uri.query = hash_to_query(h) 108 | uri.to_s 109 | end 110 | 111 | def proxy_url 112 | @proxy_url || (cas_base_url + "/proxy") 113 | end 114 | 115 | def validate_service_ticket(st) 116 | uri = URI.parse(validate_url) 117 | h = uri.query ? query_to_hash(uri.query) : {} 118 | h['service'] = st.service 119 | h['ticket'] = st.ticket 120 | h['renew'] = "1" if st.renew 121 | h['pgtUrl'] = proxy_callback_url if proxy_callback_url 122 | uri.query = hash_to_query(h) 123 | 124 | response = request_cas_response(uri, ValidationResponse) 125 | st.user = response.user 126 | st.extra_attributes = response.extra_attributes 127 | st.pgt_iou = response.pgt_iou 128 | st.success = response.is_success? 129 | st.failure_code = response.failure_code 130 | st.failure_message = response.failure_message 131 | 132 | return st 133 | end 134 | alias validate_proxy_ticket validate_service_ticket 135 | 136 | # Returns true if the configured CAS server is up and responding; 137 | # false otherwise. 138 | def cas_server_is_up? 139 | uri = URI.parse(login_url) 140 | 141 | log.debug "Checking if CAS server at URI '#{uri}' is up..." 142 | 143 | https = https_connection(uri) 144 | 145 | begin 146 | raw_res = https.start do |conn| 147 | conn.get("#{uri.path}?#{uri.query}") 148 | end 149 | rescue Errno::ECONNREFUSED => e 150 | log.warn "CAS server did not respond! (#{e.inspect})" 151 | return false 152 | end 153 | 154 | log.debug "CAS server responded with #{raw_res.inspect}:\n#{raw_res.body}" 155 | 156 | return raw_res.kind_of?(Net::HTTPSuccess) 157 | end 158 | 159 | # Requests a login using the given credentials for the given service; 160 | # returns a LoginResponse object. 161 | def login_to_service(credentials, service) 162 | lt = request_login_ticket 163 | 164 | data = credentials.merge( 165 | :lt => lt, 166 | :service => service 167 | ) 168 | 169 | res = submit_data_to_cas(login_url, data) 170 | response = CASClient::LoginResponse.new(res) 171 | 172 | if response.is_success? 173 | log.info("Login was successful for ticket: #{response.ticket.inspect}.") 174 | end 175 | 176 | return response 177 | end 178 | 179 | # Requests a login ticket from the CAS server for use in a login request; 180 | # returns a LoginTicket object. 181 | # 182 | # This only works with RubyCAS-Server, since obtaining login 183 | # tickets in this manner is not part of the official CAS spec. 184 | def request_login_ticket 185 | uri = URI.parse(login_url+'Ticket') 186 | https = https_connection(uri) 187 | res = https.post(uri.path, ';') 188 | 189 | raise CASException, res.body unless res.kind_of? Net::HTTPSuccess 190 | 191 | res.body.strip 192 | end 193 | 194 | # Requests a proxy ticket from the CAS server for the given service 195 | # using the given pgt (proxy granting ticket); returns a ProxyTicket 196 | # object. 197 | # 198 | # The pgt required to request a proxy ticket is obtained as part of 199 | # a ValidationResponse. 200 | def request_proxy_ticket(pgt, target_service) 201 | uri = URI.parse(proxy_url) 202 | h = uri.query ? query_to_hash(uri.query) : {} 203 | h['pgt'] = pgt.ticket 204 | h['targetService'] = target_service 205 | uri.query = hash_to_query(h) 206 | 207 | response = request_cas_response(uri, ProxyResponse) 208 | 209 | pt = ProxyTicket.new(response.proxy_ticket, target_service) 210 | pt.success = response.is_success? 211 | pt.failure_code = response.failure_code 212 | pt.failure_message = response.failure_message 213 | 214 | return pt 215 | end 216 | 217 | def retrieve_proxy_granting_ticket(pgt_iou) 218 | pgt = @ticket_store.retrieve_pgt(pgt_iou) 219 | 220 | raise CASException, "Couldn't find pgt for pgt_iou #{pgt_iou}" unless pgt 221 | 222 | ProxyGrantingTicket.new(pgt, pgt_iou) 223 | end 224 | 225 | def add_service_to_login_url(service_url) 226 | uri = URI.parse(login_url) 227 | uri.query = (uri.query ? uri.query + "&" : "") + "service=#{CGI.escape(service_url)}" 228 | uri.to_s 229 | end 230 | 231 | private 232 | 233 | def https_connection(uri) 234 | https = Net::HTTP::Proxy(proxy_host, proxy_port).new(uri.host, uri.port) 235 | https.use_ssl = (uri.scheme == 'https') 236 | https.verify_mode = (@force_ssl_verification ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE) 237 | https 238 | end 239 | 240 | # Fetches a CAS response of the given type from the given URI. 241 | # Type should be either ValidationResponse or ProxyResponse. 242 | def request_cas_response(uri, type, options={}) 243 | log.debug "Requesting CAS response for URI #{uri}" 244 | 245 | uri = URI.parse(uri) unless uri.kind_of? URI 246 | https = https_connection(uri) 247 | begin 248 | raw_res = https.start do |conn| 249 | conn.get("#{uri.path}?#{uri.query}") 250 | end 251 | rescue Errno::ECONNREFUSED => e 252 | log.error "CAS server did not respond! (#{e.inspect})" 253 | raise "The CAS authentication server at #{uri} is not responding!" 254 | end 255 | 256 | # We accept responses of type 422 since RubyCAS-Server generates these 257 | # in response to requests from the client that are processable but contain 258 | # invalid CAS data (for example an invalid service ticket). 259 | if raw_res.kind_of?(Net::HTTPSuccess) || raw_res.code.to_i == 422 260 | log.debug "CAS server responded with #{raw_res.inspect}:\n#{raw_res.body}" 261 | else 262 | log.error "CAS server responded with an error! (#{raw_res.inspect})" 263 | raise "The CAS authentication server at #{uri} responded with an error (#{raw_res.inspect})!" 264 | end 265 | 266 | type.new(raw_res.body, @conf_options) 267 | end 268 | 269 | # Submits some data to the given URI and returns a Net::HTTPResponse. 270 | def submit_data_to_cas(uri, data) 271 | uri = URI.parse(uri) unless uri.kind_of? URI 272 | req = Net::HTTP::Post.new(uri.path) 273 | req.set_form_data(data, ';') 274 | https = https_connection(uri) 275 | https.start {|conn| conn.request(req) } 276 | end 277 | 278 | def query_to_hash(query) 279 | CGI.parse(query) 280 | end 281 | 282 | def hash_to_query(hash) 283 | pairs = [] 284 | hash.each do |k, vals| 285 | vals = [vals] unless vals.kind_of? Array 286 | vals.each {|v| pairs << (v.nil? ? CGI.escape(k) : "#{CGI.escape(k)}=#{CGI.escape(v)}")} 287 | end 288 | pairs.join("&") 289 | end 290 | end 291 | end 292 | -------------------------------------------------------------------------------- /lib/casclient/frameworks/rails/cas_proxy_callback_controller.rb: -------------------------------------------------------------------------------- 1 | require 'action_controller' 2 | # Rails controller that responds to proxy generating ticket callbacks from the CAS server and allows 3 | # for retrieval of those PGTs. 4 | class CasProxyCallbackController < ActionController::Base 5 | 6 | # Receives a proxy granting ticket from the CAS server and stores it in the database. 7 | # Note that this action should ALWAYS be called via https, otherwise you have a gaping security hole. 8 | # In fact, the JA-SIG implementation of the CAS server will refuse to send PGTs to non-https URLs. 9 | def receive_pgt 10 | #FIXME: these checks don't work because REMOTE_HOST doesn't work consistently under all web servers (for example it doesn't work at all under mongrel) 11 | # ... need to find a reliable way to check if the request came through from a reverse HTTPS proxy -- until then I'm disabling this check 12 | #render_error "PGTs can be received only via HTTPS or local connections." and return unless 13 | # request.ssl? or request.env['REMOTE_HOST'] == "127.0.0.1" 14 | 15 | pgtIou = params['pgtIou'] 16 | 17 | # CAS Protocol spec says that the argument should be called 'pgt', but the JA-SIG CAS server seems to use pgtId. 18 | # To accomodate this, we check for both parameters, although 'pgt' takes precedence over 'pgtId'. 19 | pgtId = params['pgt'] || params['pgtId'] 20 | 21 | # We need to render a response with HTTP status code 200 when no pgtIou/pgtId is specified because CAS seems first 22 | # call the action without any parameters (maybe to check if the server responds correctly) 23 | render :text => "Okay, the server is up, but please specify a pgtIou and pgtId." and return unless pgtIou and pgtId 24 | 25 | # TODO: pstore contents should probably be encrypted... 26 | 27 | if defined?(RubyCAS::Filter) 28 | casclient = RubyCAS::Filter.client 29 | else 30 | casclient = CASClient::Frameworks::Rails::Filter.client 31 | end 32 | 33 | casclient.ticket_store.save_pgt_iou(pgtIou, pgtId) 34 | 35 | render :text => "PGT received. Thank you!" and return 36 | end 37 | 38 | private 39 | def render_error(msg) 40 | # Note that the error messages are mostly just for debugging, since the CAS server never reads them. 41 | render :text => msg, :status => 500 42 | end 43 | 44 | def open_pstore 45 | PStore.new("#{::Rails.root}/tmp/cas_pgt.pstore") 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/casclient/frameworks/rails/filter.rb: -------------------------------------------------------------------------------- 1 | module CASClient 2 | module Frameworks 3 | module Rails 4 | class Filter 5 | cattr_reader :config, :log, :client, :fake_user, :fake_extra_attributes 6 | 7 | # These are initialized when you call configure. 8 | @@config = nil 9 | @@client = nil 10 | @@log = nil 11 | @@fake_user = nil 12 | @@fake_extra_attributes = nil 13 | 14 | def self.before(controller) 15 | self.filter controller 16 | end 17 | 18 | class << self 19 | def filter(controller) 20 | raise "Cannot use the CASClient filter because it has not yet been configured." if config.nil? 21 | 22 | if @@fake_user 23 | controller.session[client.username_session_key] = @@fake_user 24 | controller.session[:casfilteruser] = @@fake_user 25 | controller.session[client.extra_attributes_session_key] = @@fake_extra_attributes if @@fake_extra_attributes 26 | return true 27 | end 28 | 29 | last_st = controller.session[:cas_last_valid_ticket] 30 | last_st_service = controller.session[:cas_last_valid_ticket_service] 31 | 32 | if single_sign_out(controller) 33 | controller.send(:render, :text => "CAS Single-Sign-Out request intercepted.") 34 | return false 35 | end 36 | 37 | st = read_ticket(controller) 38 | 39 | if st && last_st && 40 | last_st == st.ticket && 41 | last_st_service == st.service 42 | # warn() rather than info() because we really shouldn't be re-validating the same ticket. 43 | # The only situation where this is acceptable is if the user manually does a refresh and 44 | # the same ticket happens to be in the URL. 45 | log.warn("Re-using previously validated ticket since the ticket id and service are the same.") 46 | return true 47 | elsif last_st && 48 | !config[:authenticate_on_every_request] && 49 | controller.session[client.username_session_key] 50 | # Re-use the previous ticket if the user already has a local CAS session (i.e. if they were already 51 | # previously authenticated for this service). This is to prevent redirection to the CAS server on every 52 | # request. 53 | # 54 | # This behaviour can be disabled (so that every request is routed through the CAS server) by setting 55 | # the :authenticate_on_every_request config option to true. However, this is not desirable since 56 | # it will almost certainly break POST request, AJAX calls, etc. 57 | log.debug "Existing local CAS session detected for #{controller.session[client.username_session_key].inspect}. "+ 58 | "Previous ticket #{last_st.inspect} will be re-used." 59 | return true 60 | end 61 | 62 | if st 63 | client.validate_service_ticket(st) unless st.has_been_validated? 64 | 65 | if st.is_valid? 66 | #if is_new_session 67 | log.info("Ticket #{st.ticket.inspect} for service #{st.service.inspect} belonging to user #{st.user.inspect} is VALID.") 68 | controller.session[client.username_session_key] = st.user.dup 69 | controller.session[client.extra_attributes_session_key] = HashWithIndifferentAccess.new(st.extra_attributes) if st.extra_attributes 70 | 71 | if st.extra_attributes 72 | log.debug("Extra user attributes provided along with ticket #{st.ticket.inspect}: #{st.extra_attributes.inspect}.") 73 | end 74 | 75 | # RubyCAS-Client 1.x used :casfilteruser as it's username session key, 76 | # so we need to set this here to ensure compatibility with configurations 77 | # built around the old client. 78 | controller.session[:casfilteruser] = st.user 79 | 80 | if config[:enable_single_sign_out] 81 | client.ticket_store.store_service_session_lookup(st, controller) 82 | end 83 | #end 84 | 85 | # Store the ticket in the session to avoid re-validating the same service 86 | # ticket with the CAS server. 87 | controller.session[:cas_last_valid_ticket] = st.ticket 88 | controller.session[:cas_last_valid_ticket_service] = st.service 89 | 90 | if st.pgt_iou 91 | unless controller.session[:cas_pgt] && controller.session[:cas_pgt].ticket && controller.session[:cas_pgt].iou == st.pgt_iou 92 | log.info("Receipt has a proxy-granting ticket IOU. Attempting to retrieve the proxy-granting ticket...") 93 | pgt = client.retrieve_proxy_granting_ticket(st.pgt_iou) 94 | 95 | if pgt 96 | log.debug("Got PGT #{pgt.ticket.inspect} for PGT IOU #{pgt.iou.inspect}. This will be stored in the session.") 97 | controller.session[:cas_pgt] = pgt 98 | # For backwards compatibility with RubyCAS-Client 1.x configurations... 99 | controller.session[:casfilterpgt] = pgt 100 | else 101 | log.error("Failed to retrieve a PGT for PGT IOU #{st.pgt_iou}!") 102 | end 103 | else 104 | log.info("PGT is present in session and PGT IOU #{st.pgt_iou} matches the saved PGT IOU. Not retrieving new PGT.") 105 | end 106 | end 107 | return true 108 | else 109 | log.warn("Ticket #{st.ticket.inspect} failed validation -- #{st.failure_code}: #{st.failure_message}") 110 | unauthorized!(controller, st) 111 | return false 112 | end 113 | else # no service ticket was present in the request 114 | if returning_from_gateway?(controller) 115 | log.info "Returning from CAS gateway without authentication." 116 | 117 | # unset, to allow for the next request to be authenticated if necessary 118 | controller.session[:cas_sent_to_gateway] = false 119 | 120 | if use_gatewaying? 121 | log.info "This CAS client is configured to use gatewaying, so we will permit the user to continue without authentication." 122 | controller.session[client.username_session_key] = nil 123 | return true 124 | else 125 | log.warn "The CAS client is NOT configured to allow gatewaying, yet this request was gatewayed. Something is not right!" 126 | end 127 | end 128 | 129 | unauthorized!(controller) 130 | return false 131 | end 132 | rescue OpenSSL::SSL::SSLError 133 | log.error("SSL Error: hostname was not match with the server certificate. You can try to disable the ssl verification with a :force_ssl_verification => false in your configurations file.") 134 | unauthorized!(controller) 135 | return false 136 | end 137 | 138 | def configure(config) 139 | @@config = config 140 | @@config[:logger] = ::Rails.logger unless @@config[:logger] 141 | @@client = CASClient::Client.new(config) 142 | @@log = client.log 143 | end 144 | 145 | # used to allow faking for testing 146 | # with cucumber and other tools. 147 | # use like 148 | # CASClient::Frameworks::Rails::Filter.fake("homer") 149 | # you can also fake extra attributes by including a second parameter 150 | # CASClient::Frameworks::Rails::Filter.fake("homer", {:roles => ['dad', 'husband']}) 151 | def fake(username, extra_attributes = nil) 152 | @@fake_user = username 153 | @@fake_extra_attributes = extra_attributes 154 | end 155 | 156 | def use_gatewaying? 157 | @@config[:use_gatewaying] 158 | end 159 | 160 | # Returns the login URL for the current controller. 161 | # Useful when you want to provide a "Login" link in a GatewayFilter'ed 162 | # action. 163 | def login_url(controller) 164 | service_url = read_service_url(controller) 165 | url = client.add_service_to_login_url(service_url) 166 | log.debug("Generated login url: #{url}") 167 | return url 168 | end 169 | 170 | # allow controllers to reuse the existing config to auto-login to 171 | # the service 172 | # 173 | # Use this from within a controller. Pass the controller, the 174 | # login-credentials and the path that you want the user 175 | # resdirected to on success. 176 | # 177 | # When writing a login-action you must check the return-value of 178 | # the response to see if it failed! 179 | # 180 | # If it worked - you need to redirect the user to the service - 181 | # path, because that has the ticket that will *actually* log them 182 | # into your system 183 | # 184 | # example: 185 | # def autologin 186 | # resp = CASClient::Frameworks::Rails::Filter.login_to_service(self, credentials, dashboard_url) 187 | # if resp.is_faiulure? 188 | # flash[:error] = 'Login failed' 189 | # render :action => 'login' 190 | # else 191 | # return redirect_to(@resp.service_redirect_url) 192 | # end 193 | # end 194 | def login_to_service(controller, credentials, return_path) 195 | resp = @@client.login_to_service(credentials, return_path) 196 | if resp.is_failure? 197 | log.info("Validation failed for service #{return_path.inspect} reason: '#{resp.failure_message}'") 198 | else 199 | log.info("Ticket #{resp.ticket.inspect} for service #{return_path.inspect} is VALID.") 200 | end 201 | 202 | resp 203 | end 204 | 205 | # Clears the given controller's local Rails session, does some local 206 | # CAS cleanup, and redirects to the CAS logout page. Additionally, the 207 | # request.referer value from the controller instance 208 | # is passed to the CAS server as a 'destination' parameter. This 209 | # allows RubyCAS server to provide a follow-up login page allowing 210 | # the user to log back in to the service they just logged out from 211 | # using a different username and password. Other CAS server 212 | # implemenations may use this 'destination' parameter in different 213 | # ways. 214 | # If given, the optional service URL overrides 215 | # request.referer. 216 | def logout(controller, service = nil) 217 | referer = service || controller.request.referer 218 | st = controller.session[:cas_last_valid_ticket] 219 | @@client.ticket_store.cleanup_service_session_lookup(st) if st 220 | controller.send(:reset_session) 221 | controller.send(:redirect_to, client.logout_url(referer)) 222 | end 223 | 224 | def unauthorized!(controller, vr = nil) 225 | format = nil 226 | unless controller.request.format.nil? 227 | format = controller.request.format.to_sym 228 | end 229 | format = (format == :js ? :json : format) 230 | case format 231 | when :xml, :json 232 | if vr 233 | case format 234 | when :xml 235 | controller.send(:render, :xml => { :error => vr.failure_message }.to_xml(:root => 'errors'), :status => :unauthorized) 236 | when :json 237 | controller.send(:render, :json => { :errors => { :error => vr.failure_message }}, :status => :unauthorized) 238 | end 239 | else 240 | controller.send(:head, :unauthorized) 241 | end 242 | else 243 | redirect_to_cas_for_authentication(controller) 244 | end 245 | end 246 | 247 | def redirect_to_cas_for_authentication(controller) 248 | redirect_url = login_url(controller) 249 | 250 | if use_gatewaying? 251 | controller.session[:cas_sent_to_gateway] = true 252 | redirect_url << "&gateway=true" 253 | else 254 | controller.session[:cas_sent_to_gateway] = false 255 | end 256 | 257 | if controller.session[:previous_redirect_to_cas] && 258 | controller.session[:previous_redirect_to_cas] > (Time.now - 1.second) 259 | log.warn("Previous redirect to the CAS server was less than a second ago. The client at #{controller.request.remote_ip.inspect} may be stuck in a redirection loop!") 260 | controller.session[:cas_validation_retry_count] ||= 0 261 | 262 | if controller.session[:cas_validation_retry_count] > 3 263 | log.error("Redirection loop intercepted. Client at #{controller.request.remote_ip.inspect} will be redirected back to login page and forced to renew authentication.") 264 | redirect_url += "&renew=1&redirection_loop_intercepted=1" 265 | end 266 | 267 | controller.session[:cas_validation_retry_count] += 1 268 | else 269 | controller.session[:cas_validation_retry_count] = 0 270 | end 271 | controller.session[:previous_redirect_to_cas] = Time.now 272 | 273 | log.debug("Redirecting to #{redirect_url.inspect}") 274 | controller.send(:redirect_to, redirect_url) 275 | end 276 | 277 | private 278 | def single_sign_out(controller) 279 | 280 | # Avoid calling raw_post (which may consume the post body) if 281 | # this seems to be a file upload 282 | if content_type = controller.request.headers["CONTENT_TYPE"] && 283 | content_type =~ %r{^multipart/} 284 | return false 285 | end 286 | 287 | if controller.request.post? && 288 | controller.params['logoutRequest'] && 289 | #This next line checks the logoutRequest value for both its regular and URI.escape'd form. I couldn't get 290 | #it to work without URI.escaping it from rubycas server's side, this way it will work either way. 291 | [controller.params['logoutRequest'],URI.unescape(controller.params['logoutRequest'])].find{|xml| xml =~ 292 | %r{^(.*)}m} 293 | # TODO: Maybe check that the request came from the registered CAS server? Although this might be 294 | # pointless since it's easily spoofable... 295 | si = $~[1] 296 | 297 | unless config[:enable_single_sign_out] 298 | log.warn "Ignoring single-sign-out request for CAS session #{si.inspect} because ssout functionality is not enabled (see the :enable_single_sign_out config option)." 299 | return false 300 | end 301 | 302 | log.debug "Intercepted single-sign-out request for CAS session #{si.inspect}." 303 | 304 | @@client.ticket_store.process_single_sign_out(si) 305 | 306 | # Return true to indicate that a single-sign-out request was detected 307 | # and that further processing of the request is unnecessary. 308 | return true 309 | end 310 | 311 | # This is not a single-sign-out request. 312 | return false 313 | end 314 | 315 | def read_ticket(controller) 316 | ticket = controller.params[:ticket] 317 | 318 | return nil unless ticket 319 | 320 | log.debug("Request contains ticket #{ticket.inspect}.") 321 | 322 | if ticket =~ /^PT-/ 323 | ProxyTicket.new(ticket, read_service_url(controller), controller.params[:renew]) 324 | else 325 | ServiceTicket.new(ticket, read_service_url(controller), controller.params[:renew]) 326 | end 327 | end 328 | 329 | def returning_from_gateway?(controller) 330 | controller.session[:cas_sent_to_gateway] 331 | end 332 | 333 | def read_service_url(controller) 334 | if config[:service_url] 335 | log.debug("Using explicitly set service url: #{config[:service_url]}") 336 | return config[:service_url] 337 | end 338 | 339 | params = {}.with_indifferent_access 340 | params.update(controller.request.query_parameters) 341 | params.update(controller.request.path_parameters) 342 | params.delete(:ticket) 343 | service_url = controller.url_for(params) 344 | log.debug("Guessed service url: #{service_url.inspect}") 345 | return service_url 346 | end 347 | end 348 | end 349 | 350 | class GatewayFilter < Filter 351 | def self.use_gatewaying? 352 | return true unless @@config[:use_gatewaying] == false 353 | end 354 | end 355 | end 356 | end 357 | end 358 | -------------------------------------------------------------------------------- /lib/casclient/responses.rb: -------------------------------------------------------------------------------- 1 | module CASClient 2 | module XmlResponse 3 | attr_reader :xml, :parse_datetime 4 | attr_reader :failure_code, :failure_message 5 | 6 | def check_and_parse_xml(raw_xml) 7 | begin 8 | doc = REXML::Document.new(raw_xml, :raw => :all) 9 | rescue REXML::ParseException => e 10 | raise BadResponseException, 11 | "MALFORMED CAS RESPONSE:\n#{raw_xml.inspect}\n\nEXCEPTION:\n#{e}" 12 | end 13 | 14 | unless doc.elements && doc.elements["cas:serviceResponse"] 15 | raise BadResponseException, 16 | "This does not appear to be a valid CAS response (missing cas:serviceResponse root element)!\nXML DOC:\n#{doc.to_s}" 17 | end 18 | 19 | return doc.elements["cas:serviceResponse"].elements[1] 20 | end 21 | 22 | def to_s 23 | xml.to_s 24 | end 25 | end 26 | 27 | # Represents a response from the CAS server to a 'validate' request 28 | # (i.e. after validating a service/proxy ticket). 29 | class ValidationResponse 30 | include XmlResponse 31 | 32 | attr_reader :protocol, :user, :pgt_iou, :proxies, :extra_attributes 33 | 34 | def initialize(raw_text, options={}) 35 | parse(raw_text, options) 36 | end 37 | 38 | def parse(raw_text, options) 39 | raise BadResponseException, 40 | "CAS response is empty/blank." if raw_text.to_s.empty? 41 | @parse_datetime = Time.now 42 | if raw_text =~ /^(yes|no)\n(.*?)\n$/m 43 | @protocol = 1.0 44 | @valid = $~[1] == 'yes' 45 | @user = $~[2] 46 | return 47 | end 48 | 49 | @xml = check_and_parse_xml(raw_text) 50 | 51 | # if we got this far then we've got a valid XML response, so we're doing CAS 2.0 52 | @protocol = 2.0 53 | 54 | if is_success? 55 | cas_user = @xml.elements["cas:user"] 56 | @user = cas_user.text.strip if cas_user 57 | @pgt_iou = @xml.elements["cas:proxyGrantingTicket"].text.strip if @xml.elements["cas:proxyGrantingTicket"] 58 | 59 | proxy_els = @xml.elements.to_a('//cas:authenticationSuccess/cas:proxies/cas:proxy') 60 | if proxy_els.size > 0 61 | @proxies = [] 62 | proxy_els.each do |el| 63 | @proxies << el.text 64 | end 65 | end 66 | 67 | @extra_attributes = {} 68 | @xml.elements.to_a('//cas:authenticationSuccess/cas:attributes/* | //cas:authenticationSuccess/*[local-name() != \'proxies\' and local-name() != \'proxyGrantingTicket\' and local-name() != \'user\' and local-name() != \'attributes\']').each do |el| 69 | inner_text = el.cdatas.length > 0 ? el.cdatas.join('') : el.text 70 | name = el.name 71 | unless (attrs = el.attributes).empty? 72 | name = attrs['name'] 73 | inner_text = attrs['value'] 74 | end 75 | @extra_attributes.merge! name => inner_text 76 | end 77 | 78 | # unserialize extra attributes 79 | @extra_attributes.each do |k, v| 80 | @extra_attributes[k] = parse_extra_attribute_value(v, options[:encode_extra_attributes_as]) 81 | end 82 | elsif is_failure? 83 | @failure_code = @xml.elements['//cas:authenticationFailure'].attributes['code'] 84 | @failure_message = @xml.elements['//cas:authenticationFailure'].text.strip 85 | else 86 | # this should never happen, since the response should already have been recognized as invalid 87 | raise BadResponseException, "BAD CAS RESPONSE:\n#{raw_text.inspect}\n\nXML DOC:\n#{doc.inspect}" 88 | end 89 | end 90 | 91 | def parse_extra_attribute_value(value, encode_extra_attributes_as) 92 | attr_value = if value.to_s.empty? 93 | nil 94 | elsif !encode_extra_attributes_as 95 | begin 96 | YAML.load(value) 97 | rescue ArgumentError => e 98 | raise ArgumentError, "Error parsing extra attribute with value #{value} as YAML: #{e}" 99 | end 100 | else 101 | if encode_extra_attributes_as == :json 102 | begin 103 | JSON.parse(value) 104 | rescue JSON::ParserError 105 | value 106 | end 107 | elsif encode_extra_attributes_as == :raw 108 | value 109 | else 110 | YAML.load(value) 111 | end 112 | end 113 | 114 | unless attr_value.kind_of?(Enumerable) || attr_value.kind_of?(TrueClass) || attr_value.kind_of?(FalseClass) || attr_value.nil? 115 | attr_value.to_s 116 | else 117 | attr_value 118 | end 119 | end 120 | 121 | def is_success? 122 | (instance_variable_defined?(:@valid) && @valid) || (protocol > 1.0 && xml.name == "authenticationSuccess") 123 | end 124 | 125 | def is_failure? 126 | (instance_variable_defined?(:@valid) && !@valid) || (protocol > 1.0 && xml.name == "authenticationFailure" ) 127 | end 128 | end 129 | 130 | # Represents a response from the CAS server to a proxy ticket request 131 | # (i.e. after requesting a proxy ticket). 132 | class ProxyResponse 133 | include XmlResponse 134 | 135 | attr_reader :proxy_ticket 136 | 137 | def initialize(raw_text, options={}) 138 | parse(raw_text) 139 | end 140 | 141 | def parse(raw_text) 142 | raise BadResponseException, 143 | "CAS response is empty/blank." if raw_text.to_s.empty? 144 | @parse_datetime = Time.now 145 | 146 | @xml = check_and_parse_xml(raw_text) 147 | 148 | if is_success? 149 | @proxy_ticket = @xml.elements["cas:proxyTicket"].text.strip if @xml.elements["cas:proxyTicket"] 150 | elsif is_failure? 151 | @failure_code = @xml.elements['//cas:proxyFailure'].attributes['code'] 152 | @failure_message = @xml.elements['//cas:proxyFailure'].text.strip 153 | else 154 | # this should never happen, since the response should already have been recognized as invalid 155 | raise BadResponseException, "BAD CAS RESPONSE:\n#{raw_text.inspect}\n\nXML DOC:\n#{doc.inspect}" 156 | end 157 | 158 | end 159 | 160 | def is_success? 161 | xml.name == "proxySuccess" 162 | end 163 | 164 | def is_failure? 165 | xml.name == "proxyFailure" 166 | end 167 | end 168 | 169 | # Represents a response from the CAS server to a login request 170 | # (i.e. after submitting a username/password). 171 | class LoginResponse 172 | attr_reader :tgt, :ticket, :service_redirect_url 173 | attr_reader :failure_message 174 | 175 | def initialize(http_response = nil, options={}) 176 | parse_http_response(http_response) if http_response 177 | end 178 | 179 | def parse_http_response(http_response) 180 | header = http_response.to_hash 181 | 182 | # FIXME: this regexp might be incorrect... 183 | if header['set-cookie'] && 184 | header['set-cookie'].first && 185 | header['set-cookie'].first =~ /tgt=([^&]+);/ 186 | @tgt = $~[1] 187 | end 188 | 189 | location = header['location'].first if header['location'] && header['location'].first 190 | if location =~ /ticket=([^&]+)/ 191 | @ticket = $~[1] 192 | end 193 | 194 | # Legacy check. CAS Server used to return a 200 (Success) or a 302 (Found) on successful authentication. 195 | # This behavior should be deprecated at some point in the future. 196 | legacy_valid_ticket = (http_response.kind_of?(Net::HTTPSuccess) || http_response.kind_of?(Net::HTTPFound)) && @ticket.present? 197 | 198 | # If using rubycas-server 1.1.0+ 199 | valid_ticket = http_response.kind_of?(Net::HTTPSeeOther) && @ticket.present? 200 | 201 | if !legacy_valid_ticket && !valid_ticket 202 | @failure = true 203 | # Try to extract the error message -- this only works with RubyCAS-Server. 204 | # For other servers we just return the entire response body (i.e. the whole error page). 205 | body = http_response.body 206 | if body =~ /
(.*?)<\/div>/m 207 | @failure_message = $~[1].strip 208 | else 209 | @failure_message = body 210 | end 211 | end 212 | 213 | @service_redirect_url = location 214 | end 215 | 216 | def is_success? 217 | !@failure && !ticket.to_s.empty? 218 | end 219 | 220 | def is_failure? 221 | @failure == true 222 | end 223 | end 224 | 225 | class BadResponseException < CASException 226 | end 227 | end 228 | -------------------------------------------------------------------------------- /lib/casclient/tickets.rb: -------------------------------------------------------------------------------- 1 | module CASClient 2 | # Represents a CAS service ticket. 3 | class ServiceTicket 4 | attr_reader :ticket, :service, :renew 5 | attr_accessor :user, :extra_attributes, :pgt_iou, :success, :failure_code, :failure_message 6 | 7 | def initialize(ticket, service, renew = false) 8 | @ticket = ticket 9 | @service = service 10 | @renew = renew 11 | end 12 | 13 | def is_valid? 14 | success 15 | end 16 | 17 | def has_been_validated? 18 | not user.nil? 19 | end 20 | end 21 | 22 | # Represents a CAS proxy ticket. 23 | class ProxyTicket < ServiceTicket 24 | end 25 | 26 | class ProxyGrantingTicket 27 | attr_reader :ticket, :iou 28 | 29 | def initialize(ticket, iou) 30 | @ticket = ticket 31 | @iou = iou 32 | end 33 | 34 | def to_s 35 | ticket 36 | end 37 | end 38 | end -------------------------------------------------------------------------------- /lib/casclient/tickets/storage.rb: -------------------------------------------------------------------------------- 1 | module CASClient 2 | module Tickets 3 | module Storage 4 | class AbstractTicketStore 5 | 6 | attr_accessor :log 7 | def log 8 | @log ||= CASClient::LoggerWrapper.new 9 | end 10 | 11 | def process_single_sign_out(st) 12 | 13 | session_id, session = get_session_for_service_ticket(st) 14 | if session 15 | session.destroy 16 | log.debug("Destroyed #{session.inspect} for session #{session_id.inspect} corresponding to service ticket #{st.inspect}.") 17 | else 18 | log.debug("Data for session #{session_id.inspect} was not found. It may have already been cleared by a local CAS logout request.") 19 | end 20 | 21 | if session_id 22 | log.info("Single-sign-out for service ticket #{session_id.inspect} completed successfuly.") 23 | else 24 | log.debug("No session id found for CAS ticket #{st}") 25 | end 26 | end 27 | 28 | def get_session_for_service_ticket(st) 29 | session_id = read_service_session_lookup(st) 30 | unless session_id.nil? 31 | # This feels a bit hackish, but there isn't really a better way to go about it that I am aware of yet 32 | session = ActiveRecord::SessionStore.session_class.find(:first, :conditions => {:session_id => session_id}) 33 | else 34 | log.warn("Couldn't destroy session service ticket #{st} because no corresponding session id could be found.") 35 | end 36 | [session_id, session] 37 | end 38 | 39 | def store_service_session_lookup(st, controller) 40 | raise 'Implement this in a subclass!' 41 | end 42 | 43 | def cleanup_service_session_lookup(st) 44 | raise 'Implement this in a subclass!' 45 | end 46 | 47 | def save_pgt_iou(pgt_iou, pgt) 48 | raise 'Implement this in a subclass!' 49 | end 50 | 51 | def retrieve_pgt(pgt_iou) 52 | raise 'Implement this in a subclass!' 53 | end 54 | 55 | protected 56 | def read_service_session_lookup(st) 57 | raise 'Implement this in a subclass!' 58 | end 59 | 60 | def session_id_from_controller(controller) 61 | session_id = controller.request.session_options[:id] || controller.session.session_id 62 | raise CASClient::CASException, "Failed to extract session_id from controller" if session_id.nil? 63 | session_id 64 | end 65 | end 66 | 67 | # A Ticket Store that keeps it's tickets in a directory on the local filesystem. 68 | # Service tickets are stored under tmp/sessions by default 69 | # and Proxy Granting Tickets and their IOUs are stored in tmp/cas_pgt.pstore 70 | # This Ticket Store works fine for small sites but will most likely have 71 | # concurrency problems under heavy load. It also requires that all your 72 | # worker processes have access to a shared file system. 73 | # 74 | # This ticket store takes the following config parameters 75 | # :storage_dir - The directory to store data in. Defaults to Rails.root/tmp 76 | # :service_session_lookup_dir - The directory to store Service Ticket/Session ID files in. Defaults to :storage_dir/sessions 77 | # :pgt_store_path - The location to store the pgt PStore file. Defaults to :storage_dir/cas_pgt.pstore 78 | class LocalDirTicketStore < AbstractTicketStore 79 | require 'pstore' 80 | 81 | def initialize(config={}) 82 | config ||= {} 83 | default_tmp_dir = defined?(Rails.root) ? "#{Rails.root}/tmp" : "#{Dir.pwd}/tmp" 84 | @tmp_dir = config[:storage_dir] || default_tmp_dir 85 | @service_session_lookup_dir = config[:service_session_lookup_dir] || "#{@tmp_dir}/sessions" 86 | @pgt_store_path = config[:pgt_store_path] || "#{@tmp_dir}/cas_pgt.pstore" 87 | end 88 | 89 | # Creates a file in tmp/sessions linking a SessionTicket 90 | # with the local Rails session id. The file is named 91 | # cas_sess. and its text contents is the corresponding 92 | # Rails session id. 93 | # Returns the filename of the lookup file created. 94 | def store_service_session_lookup(st, controller) 95 | raise CASException, "No service_ticket specified." if st.nil? 96 | raise CASException, "No controller specified." if controller.nil? 97 | 98 | sid = session_id_from_controller(controller) 99 | 100 | st = st.ticket if st.kind_of? ServiceTicket 101 | f = File.new(filename_of_service_session_lookup(st), 'w') 102 | f.write(sid) 103 | f.close 104 | return f.path 105 | end 106 | 107 | # Returns the local Rails session ID corresponding to the given 108 | # ServiceTicket. This is done by reading the contents of the 109 | # cas_sess. file created in a prior call to 110 | # #store_service_session_lookup. 111 | def read_service_session_lookup(st) 112 | raise CASException, "No service_ticket specified." if st.nil? 113 | 114 | st = st.ticket if st.kind_of? ServiceTicket 115 | ssl_filename = filename_of_service_session_lookup(st) 116 | return IO.read(ssl_filename) if File.exists?(ssl_filename) 117 | end 118 | 119 | # Removes a stored relationship between a ServiceTicket and a local 120 | # Rails session id. This should be called when the session is being 121 | # closed. 122 | # 123 | # See #store_service_session_lookup. 124 | def cleanup_service_session_lookup(st) 125 | raise CASException, "No service_ticket specified." if st.nil? 126 | 127 | st = st.ticket if st.kind_of? ServiceTicket 128 | ssl_filename = filename_of_service_session_lookup(st) 129 | File.delete(ssl_filename) if File.exists?(ssl_filename) 130 | end 131 | 132 | def save_pgt_iou(pgt_iou, pgt) 133 | raise CASException, "Invalid pgt_iou" if pgt_iou.nil? 134 | raise CASException, "Invalid pgt" if pgt.nil? 135 | 136 | # TODO: pstore contents should probably be encrypted... 137 | pstore = open_pstore 138 | 139 | pstore.transaction do 140 | pstore[pgt_iou] = pgt 141 | end 142 | end 143 | 144 | def retrieve_pgt(pgt_iou) 145 | raise CASException, "No pgt_iou specified. Cannot retrieve the pgt." unless pgt_iou 146 | 147 | pstore = open_pstore 148 | 149 | pgt = nil 150 | # TODO: need to periodically clean the storage, otherwise it will just keep growing 151 | pstore.transaction do 152 | pgt = pstore[pgt_iou] 153 | pstore.delete pgt_iou 154 | end 155 | 156 | raise CASException, "Invalid pgt_iou specified. Perhaps this pgt has already been retrieved?" unless pgt 157 | 158 | pgt 159 | end 160 | 161 | private 162 | 163 | # Returns the path and filename of the service session lookup file. 164 | def filename_of_service_session_lookup(st) 165 | st = st.ticket if st.kind_of? ServiceTicket 166 | return "#{@service_session_lookup_dir}/cas_sess.#{st}" 167 | end 168 | 169 | def open_pstore 170 | PStore.new(@pgt_store_path) 171 | end 172 | end 173 | end 174 | end 175 | end 176 | -------------------------------------------------------------------------------- /lib/casclient/tickets/storage/active_record_ticket_store.rb: -------------------------------------------------------------------------------- 1 | module CASClient 2 | module Tickets 3 | module Storage 4 | 5 | # A Ticket Store that keeps it's ticket in database tables using ActiveRecord. 6 | # 7 | # Services Tickets are stored in an extra column added to the ActiveRecord sessions table. 8 | # You will need to add the service_ticket column your ActiveRecord sessions table. 9 | # Proxy Granting Tickets and their IOUs are stored in the cas_pgtious table. 10 | # 11 | # This ticket store takes the following config parameters 12 | # :pgtious_table_name - the name of the table 13 | class ActiveRecordTicketStore < AbstractTicketStore 14 | 15 | def initialize(config={}) 16 | config ||= {} 17 | if config[:pgtious_table_name] 18 | CasPgtiou.set_table_name = config[:pgtious_table_name] 19 | end 20 | ActiveRecord::SessionStore.session_class = ServiceTicketAwareSession 21 | end 22 | 23 | def store_service_session_lookup(st, controller) 24 | raise CASException, "No service_ticket specified." unless st 25 | raise CASException, "No controller specified." unless controller 26 | 27 | st = st.ticket if st.kind_of? ServiceTicket 28 | session = controller.session 29 | session[:service_ticket] = st 30 | end 31 | 32 | def read_service_session_lookup(st) 33 | raise CASException, "No service_ticket specified." unless st 34 | st = st.ticket if st.kind_of? ServiceTicket 35 | session = ActiveRecord::SessionStore::Session.find_by_service_ticket(st) 36 | session ? session.session_id : nil 37 | end 38 | 39 | def cleanup_service_session_lookup(st) 40 | #no cleanup needed for this ticket store 41 | #we still raise the exception for API compliance 42 | raise CASException, "No service_ticket specified." unless st 43 | end 44 | 45 | def save_pgt_iou(pgt_iou, pgt) 46 | raise CASClient::CASException.new("Invalid pgt_iou") if pgt_iou.nil? 47 | raise CASClient::CASException.new("Invalid pgt") if pgt.nil? 48 | pgtiou = CasPgtiou.create(:pgt_iou => pgt_iou, :pgt_id => pgt) 49 | end 50 | 51 | def retrieve_pgt(pgt_iou) 52 | raise CASException, "No pgt_iou specified. Cannot retrieve the pgt." unless pgt_iou 53 | 54 | pgtiou = CasPgtiou.find_by_pgt_iou(pgt_iou) 55 | 56 | raise CASException, "Invalid pgt_iou specified. Perhaps this pgt has already been retrieved?" unless pgtiou 57 | pgt = pgtiou.pgt_id 58 | 59 | pgtiou.destroy 60 | 61 | pgt 62 | 63 | end 64 | 65 | end 66 | 67 | ACTIVE_RECORD_TICKET_STORE = ActiveRecordTicketStore 68 | 69 | class ServiceTicketAwareSession < ActiveRecord::SessionStore::Session 70 | before_save :save_service_ticket 71 | 72 | def save_service_ticket 73 | if data[:service_ticket] 74 | self.service_ticket = data[:service_ticket] 75 | end 76 | end 77 | end 78 | 79 | class CasPgtiou < ActiveRecord::Base 80 | #t.string :pgt_iou, :null => false 81 | #t.string :pgt_id, :null => false 82 | #t.timestamps 83 | end 84 | end 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /lib/rubycas-client.rb: -------------------------------------------------------------------------------- 1 | require 'casclient' 2 | -------------------------------------------------------------------------------- /lib/rubycas-client/version.rb: -------------------------------------------------------------------------------- 1 | module CasClient 2 | VERSION = "2.3.10.rc1" 3 | end 4 | -------------------------------------------------------------------------------- /rails_generators/active_record_ticket_store/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | Create a migration to add the service_ticket column to the sessions 3 | table and create the cas_pgtious table for proxy ticket storage. 4 | Pass the migration name as an optional parameter. The migration name 5 | defaults to CreateActiveRecordTicketStore. 6 | 7 | Requirements: 8 | You need to already have created the ActiveRecord::SessionStore sessions 9 | table. 10 | -------------------------------------------------------------------------------- /rails_generators/active_record_ticket_store/active_record_ticket_store_generator.rb: -------------------------------------------------------------------------------- 1 | class ActiveRecordTicketStoreGenerator < Rails::Generator::NamedBase 2 | 3 | def initialize(runtime_args, runtime_options = {}) 4 | runtime_args << 'create_active_record_ticket_store' if runtime_args.empty? 5 | super 6 | end 7 | 8 | def manifest 9 | record do |m| 10 | m.migration_template 'migration.rb', 'db/migrate', 11 | :assigns => { :session_table_name => default_session_table_name, :pgtiou_table_name => default_pgtiou_table_name } 12 | m.readme "README" 13 | end 14 | end 15 | 16 | protected 17 | def banner 18 | "Usage: #{$0} #{spec.name} [CreateActiveRecordTicketStore] [options]" 19 | end 20 | 21 | def default_session_table_name 22 | ActiveRecord::Base.pluralize_table_names ? 'session'.pluralize : 'session' 23 | end 24 | 25 | def default_pgtiou_table_name 26 | ActiveRecord::Base.pluralize_table_names ? 'cas_pgtiou'.pluralize : 'cas_pgtiou' 27 | end 28 | 29 | end 30 | -------------------------------------------------------------------------------- /rails_generators/active_record_ticket_store/templates/README: -------------------------------------------------------------------------------- 1 | You need to make sure you have already created the sessions table for the ActiveRecord::SessionStore 2 | -------------------------------------------------------------------------------- /rails_generators/active_record_ticket_store/templates/migration.rb: -------------------------------------------------------------------------------- 1 | class <%= class_name %> < ActiveRecord::Migration 2 | def self.up 3 | add_column :<%= session_table_name %>, :service_ticket, :string 4 | 5 | add_index :<%= session_table_name %>, :service_ticket 6 | 7 | create_table :<%= pgtiou_table_name %> do |t| 8 | t.string :pgt_iou, :null => false 9 | t.string :pgt_id, :null => false 10 | t.timestamps 11 | end 12 | 13 | add_index :<%= pgtiou_table_name %>, :pgt_iou, :unique => true 14 | end 15 | 16 | def self.down 17 | drop_table :<%= pgtiou_table_name %> 18 | 19 | remove_index :<%= session_table_name %>, :service_ticket 20 | 21 | remove_column :<%= session_table_name %>, :service_ticket 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /rubycas-client.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $LOAD_PATH << File.expand_path("../lib", __FILE__) 3 | require 'rubycas-client/version' 4 | 5 | Gem::Specification.new do |gem| 6 | gem.authors = ["Matt Campbell", "Matt Zukowski", "Matt Walker", "Matt Campbell"] 7 | gem.email = ["matt@soupmatt.com"] 8 | gem.summary = %q{Client library for the Central Authentication Service (CAS) protocol.} 9 | gem.description = %q{Client library for the Central Authentication Service (CAS) protocol.} 10 | gem.homepage = "https://github.com/rubycas/rubycas-client" 11 | gem.extra_rdoc_files = [ 12 | "LICENSE.txt", 13 | "README.rdoc" 14 | ] 15 | gem.licenses = ["MIT"] 16 | gem.rdoc_options = ["--main", "README.rdoc"] 17 | gem.version = CasClient::VERSION 18 | 19 | gem.files = `git ls-files`.split($\) 20 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 21 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 22 | gem.name = "rubycas-client" 23 | gem.require_paths = ["lib"] 24 | 25 | gem.add_dependency("activesupport") 26 | gem.add_development_dependency("rake") 27 | gem.add_development_dependency("database_cleaner", "~> 0.9.1") 28 | gem.add_development_dependency("json") 29 | gem.add_development_dependency("rspec") 30 | gem.add_development_dependency("appraisal") 31 | gem.add_development_dependency("rails") 32 | gem.add_development_dependency("simplecov") 33 | if defined?(JRUBY_VERSION) 34 | gem.add_development_dependency("activerecord-jdbcsqlite3-adapter") 35 | else 36 | gem.add_development_dependency("sqlite3") 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /spec/.gitignore: -------------------------------------------------------------------------------- 1 | test.*.db 2 | -------------------------------------------------------------------------------- /spec/casclient/client_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe CASClient::Client do 4 | let(:client) { CASClient::Client.new(:login_url => login_url, :cas_base_url => '')} 5 | let(:login_url) { "http://localhost:3443/"} 6 | let(:uri) { URI.parse(login_url) } 7 | let(:session) { double('session', :use_ssl= => true, :verify_mode= => true) } 8 | 9 | context "https connection" do 10 | let(:proxy) { double('proxy', :new => session) } 11 | 12 | before :each do 13 | Net::HTTP.stub :Proxy => proxy 14 | end 15 | 16 | it "sets up the session with the login url host and port" do 17 | proxy.should_receive(:new).with('localhost', 3443).and_return(session) 18 | client.send(:https_connection, uri) 19 | end 20 | 21 | it "sets up the proxy with the known proxy host and port" do 22 | client = CASClient::Client.new(:login_url => login_url, :cas_base_url => '', :proxy_host => 'foo', :proxy_port => 1234) 23 | Net::HTTP.should_receive(:Proxy).with('foo', 1234).and_return(proxy) 24 | client.send(:https_connection, uri) 25 | end 26 | end 27 | 28 | context "cas server requests" do 29 | let(:response) { double('response', :body => 'HTTP BODY', :code => '200') } 30 | let(:connection) { double('connection', :get => response, :post => response, :request => response) } 31 | 32 | before :each do 33 | client.stub(:https_connection).and_return(session) 34 | session.stub(:start).and_yield(connection) 35 | end 36 | 37 | context "cas server is up" do 38 | it "returns false if the server cannot be connected to" do 39 | connection.stub(:get).and_raise(Errno::ECONNREFUSED) 40 | client.cas_server_is_up?.should be_false 41 | end 42 | 43 | it "returns false if the request was not a success" do 44 | response.stub :kind_of? => false 45 | client.cas_server_is_up?.should be_false 46 | end 47 | 48 | it "returns true when the server is running" do 49 | response.stub :kind_of? => true 50 | client.cas_server_is_up?.should be_true 51 | end 52 | end 53 | 54 | context "request login ticket" do 55 | it "raises an exception when the request was not a success" do 56 | session.stub(:post).with("/Ticket", ";").and_return(response) 57 | response.stub :kind_of? => false 58 | lambda { 59 | client.request_login_ticket 60 | }.should raise_error(CASClient::CASException) 61 | end 62 | 63 | it "returns the response body when the request is a success" do 64 | session.stub(:post).with("/Ticket", ";").and_return(response) 65 | response.stub :kind_of? => true 66 | client.request_login_ticket.should == "HTTP BODY" 67 | end 68 | end 69 | 70 | context "request cas response" do 71 | let(:validation_response) { double('validation_response') } 72 | 73 | it "should raise an exception when the request is not a success or 422" do 74 | response.stub :kind_of? => false 75 | lambda { 76 | client.send(:request_cas_response, uri, CASClient::ValidationResponse) 77 | }.should raise_error(RuntimeError) 78 | end 79 | 80 | it "should return a ValidationResponse object when the request is a success or 422" do 81 | CASClient::ValidationResponse.stub(:new).and_return(validation_response) 82 | response.stub :kind_of? => true 83 | client.send(:request_cas_response, uri, CASClient::ValidationResponse).should == validation_response 84 | end 85 | end 86 | 87 | context "submit data to cas" do 88 | it "should return an HTTPResponse" do 89 | client.send(:submit_data_to_cas, uri, {}).should == response 90 | end 91 | end 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /spec/casclient/frameworks/rails/filter_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'action_controller' 3 | require 'casclient/frameworks/rails/filter' 4 | 5 | describe CASClient::Frameworks::Rails::Filter do 6 | 7 | before(:each) do 8 | CASClient::Frameworks::Rails::Filter.configure( 9 | :cas_base_url => 'http://test.local/', 10 | :logger => double("Logger") 11 | ) 12 | end 13 | 14 | describe "#fake" do 15 | subject { Hash.new } 16 | context "faking user without attributes" do 17 | before { CASClient::Frameworks::Rails::Filter.fake('tester@test.com') } 18 | it 'should set the session user' do 19 | CASClient::Frameworks::Rails::Filter.filter(mock_controller_with_session(nil, subject)) 20 | subject.should eq({:cas_user => 'tester@test.com', :casfilteruser => 'tester@test.com'}) 21 | end 22 | after { CASClient::Frameworks::Rails::Filter.fake(nil,nil) } 23 | end 24 | 25 | context "faking user with attributes" do 26 | before { CASClient::Frameworks::Rails::Filter.fake('tester@test.com', {:test => 'stuff', :this => 'that'}) } 27 | it 'should set the session user and attributes' do 28 | CASClient::Frameworks::Rails::Filter.filter(mock_controller_with_session(nil, subject)) 29 | subject.should eq({ :cas_user => 'tester@test.com', :casfilteruser => 'tester@test.com', :cas_extra_attributes => {:test => 'stuff', :this => 'that' }}) 30 | end 31 | after { CASClient::Frameworks::Rails::Filter.fake(nil,nil) } 32 | end 33 | end 34 | 35 | context "new valid service ticket" do 36 | it "should return successfully from filter" do 37 | 38 | pgt = CASClient::ProxyGrantingTicket.new( 39 | "PGT-1308586001r9573FAD5A8C62E134A4AA93273F226BD3F0C3A983DCCCD176", 40 | "PGTIOU-1308586001r29DC1F852C95930FE6694C1EFC64232A3359798893BC0B") 41 | 42 | raw_text = " 43 | 44 | rich.yarger@vibes.com 45 | PGTIOU-1308586001r29DC1F852C95930FE6694C1EFC64232A3359798893BC0B 46 | 47 | " 48 | response = CASClient::ValidationResponse.new(raw_text) 49 | 50 | CASClient::Client.any_instance.stub(:request_cas_response).and_return(response) 51 | CASClient::Client.any_instance.stub(:retrieve_proxy_granting_ticket).and_return(pgt) 52 | 53 | controller = mock_controller_with_session() 54 | CASClient::Frameworks::Rails::Filter.filter(controller).should eq(true) 55 | end 56 | end 57 | 58 | context "new invalid service ticket" do 59 | it "should return failure from filter" do 60 | 61 | raw_text = " 62 | Some Error Text 63 | " 64 | response = CASClient::ValidationResponse.new(raw_text) 65 | 66 | CASClient::Client.any_instance.stub(:request_cas_response).and_return(response) 67 | CASClient::Frameworks::Rails::Filter.stub(:unauthorized!) {"bogusresponse"} 68 | 69 | controller = mock_controller_with_session() 70 | CASClient::Frameworks::Rails::Filter.filter(controller).should eq(false) 71 | end 72 | end 73 | 74 | context "does not have new input service ticket" do 75 | context "with last service ticket" do 76 | it "should return failure from filter" do 77 | 78 | CASClient::Frameworks::Rails::Filter.stub(:unauthorized!) {"bogusresponse"} 79 | 80 | controller = mock_controller_with_session() 81 | controller.stub(:params) {{}} 82 | CASClient::Frameworks::Rails::Filter.filter(controller).should eq(false) 83 | end 84 | end 85 | 86 | context "sent through gateway" do 87 | context "gatewaying off" do 88 | it "should return failure from filter" do 89 | 90 | CASClient::Frameworks::Rails::Filter.stub(:unauthorized!) {"bogusresponse"} 91 | 92 | CASClient::Frameworks::Rails::Filter.config[:use_gatewaying] = false 93 | controller = mock_controller_with_session() 94 | controller.session[:cas_sent_to_gateway] = true 95 | controller.stub(:params) {{}} 96 | CASClient::Frameworks::Rails::Filter.filter(controller).should eq(false) 97 | end 98 | end 99 | 100 | context "gatewaying on" do 101 | it "should return failure from filter" do 102 | 103 | CASClient::Frameworks::Rails::Filter.config[:use_gatewaying] = true 104 | controller = mock_controller_with_session() 105 | controller.session[:cas_sent_to_gateway] = true 106 | controller.stub(:params) {{}} 107 | CASClient::Frameworks::Rails::Filter.filter(controller).should eq(true) 108 | end 109 | end 110 | end 111 | end 112 | 113 | context "has new input service ticket" do 114 | context "no PGT" do 115 | it "should return failure from filter" do 116 | 117 | raw_text = " 118 | 119 | rich.yarger@vibes.com 120 | PGTIOU-1308586001r29DC1F852C95930FE6694C1EFC64232A3359798893BC0B 121 | 122 | " 123 | response = CASClient::ValidationResponse.new(raw_text) 124 | 125 | CASClient::Client.any_instance.stub(:request_cas_response).and_return(response) 126 | CASClient::Client.any_instance.stub(:retrieve_proxy_granting_ticket).and_raise CASClient::CASException 127 | 128 | controller = mock_controller_with_session() 129 | expect { CASClient::Frameworks::Rails::Filter.filter(controller) }.to raise_error(CASClient::CASException) 130 | end 131 | end 132 | 133 | context "cannot connect to CASServer" do 134 | it "should return failure from filter" do 135 | 136 | CASClient::Client.any_instance.stub(:request_cas_response).and_raise "Some exception" 137 | 138 | controller = mock_controller_with_session() 139 | expect { CASClient::Frameworks::Rails::Filter.filter(controller) }.to raise_error(RuntimeError) 140 | end 141 | end 142 | 143 | context "matches existing service ticket" do 144 | subject { Hash.new } 145 | it "should return successfully from filter" do 146 | 147 | mock_client = CASClient::Client.new() 148 | mock_client.should_receive(:request_cas_response).at_most(0).times 149 | mock_client.should_receive(:retrieve_proxy_granting_ticket).at_most(0).times 150 | CASClient::Frameworks::Rails::Filter.send(:class_variable_set, :@@client, mock_client) 151 | 152 | subject[:cas_last_valid_ticket] = 'bogusticket' 153 | subject[:cas_last_valid_ticket_service] = 'bogusurl' 154 | controller = mock_controller_with_session(mock_post_request(), subject) 155 | CASClient::Frameworks::Rails::Filter.filter(controller).should eq(true) 156 | end 157 | end 158 | end 159 | 160 | context "controller request is missing format" do 161 | context "#unauthorized!" do 162 | it 'should not crash' do 163 | request = double('mock request') 164 | request.stub(:format).and_return(nil) 165 | 166 | controller = mock_controller_with_session(request) 167 | 168 | CASClient::Frameworks::Rails::Filter. 169 | should_receive(:redirect_to_cas_for_authentication). 170 | with(controller) 171 | 172 | CASClient::Frameworks::Rails::Filter.unauthorized!(controller) 173 | end 174 | end 175 | end 176 | end 177 | -------------------------------------------------------------------------------- /spec/casclient/tickets/storage/active_record_ticket_store_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'casclient/tickets/storage/active_record_ticket_store' 3 | 4 | describe CASClient::Tickets::Storage::ActiveRecordTicketStore do 5 | it_should_behave_like "a ticket store" 6 | end 7 | -------------------------------------------------------------------------------- /spec/casclient/tickets/storage_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'support/local_hash_ticket_store' 3 | require 'fileutils' 4 | 5 | describe CASClient::Tickets::Storage::AbstractTicketStore do 6 | describe "#store_service_session_lookup" do 7 | it "should raise an exception" do 8 | expect { subject.store_service_session_lookup("service_ticket", mock_controller_with_session) }.to raise_exception 'Implement this in a subclass!' 9 | end 10 | end 11 | describe "#cleanup_service_session_lookup" do 12 | it "should raise an exception" do 13 | expect { subject.cleanup_service_session_lookup("service_ticket") }.to raise_exception 'Implement this in a subclass!' 14 | end 15 | end 16 | describe "#save_pgt_iou" do 17 | it "should raise an exception" do 18 | expect { subject.save_pgt_iou("pgt_iou", "pgt") }.to raise_exception 'Implement this in a subclass!' 19 | end 20 | end 21 | describe "#retrieve_pgt" do 22 | it "should raise an exception" do 23 | expect { subject.retrieve_pgt("pgt_iou") }.to raise_exception 'Implement this in a subclass!' 24 | end 25 | end 26 | describe "#get_session_for_service_ticket" do 27 | it "should raise an exception" do 28 | expect { subject.get_session_for_service_ticket("service_ticket") }.to raise_exception 'Implement this in a subclass!' 29 | end 30 | end 31 | end 32 | 33 | describe CASClient::Tickets::Storage::LocalDirTicketStore do 34 | let(:dir) {File.join(SPEC_TMP_DIR, "local_dir_ticket_store")} 35 | before do 36 | FileUtils.mkdir_p(File.join(dir, "sessions")) 37 | end 38 | after do 39 | FileUtils.remove_dir(dir) 40 | end 41 | it_should_behave_like "a ticket store" do 42 | let(:ticket_store) {described_class.new(:storage_dir => dir)} 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/casclient/validation_response_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'casclient/responses.rb' 3 | 4 | describe CASClient::ValidationResponse do 5 | context "when parsing extra attributes as raw" do 6 | let(:response_text) do 7 | < 9 | 10 | 11 | Jimmy Bob 12 | 14 | 16 | 17 | 18 | 19 | 20 | RESPONSE_TEXT 21 | end 22 | 23 | subject { CASClient::ValidationResponse.new response_text, :encode_extra_attributes_as => :raw } 24 | 25 | it "sets text attributes to their string value" do 26 | subject.extra_attributes["name"].should == "Jimmy Bob" 27 | end 28 | 29 | it "preserves whitespace for CDATA" do 30 | subject.extra_attributes["status"].should == "stuff\n" 31 | end 32 | 33 | it "passes yaml through as is" do 34 | subject.extra_attributes["yaml"].should == "--- true\n" 35 | end 36 | it "passes json through as is" do 37 | subject.extra_attributes["json"].should == "{\"id\":10529}" 38 | end 39 | end 40 | 41 | context "when parsing extra attributes as yaml" do 42 | let(:response_text) do 43 | < 45 | 46 | 47 | Jimmy Bob 48 | 50 | 52 | 53 | 54 | 55 | 56 | RESPONSE_TEXT 57 | end 58 | 59 | subject { CASClient::ValidationResponse.new response_text, :encode_extra_attributes_as => :yaml } 60 | 61 | it "sets text attributes to their string value" do 62 | subject.extra_attributes["name"].should == "Jimmy Bob" 63 | end 64 | 65 | it "sets the value of boolean attributes to their boolean value" do 66 | subject.extra_attributes["falsy"].should == false 67 | subject.extra_attributes["truthy"].should == true 68 | end 69 | end 70 | 71 | context "when parsing extra attributes as JSON" do 72 | let(:response_text) do 73 | < 75 | 76 | 77 | Jack 78 | 92.5 79 | 80 | 81 | 82 | 83 | - 10 84 | 86 | 88 | 89 | 90 | 91 | RESPONSE_TEXT 92 | end 93 | 94 | subject { CASClient::ValidationResponse.new response_text, :encode_extra_attributes_as => :json } 95 | 96 | it "sets the value of non-CDATA escaped empty attribute to nil" do 97 | subject.extra_attributes["mobile_phone"].should be_nil 98 | end 99 | 100 | it "sets the value of CDATA escaped empty attribute to nil" do 101 | subject.extra_attributes["global_roles"].should be_nil 102 | end 103 | 104 | it "sets the value of literal attributes to their value" do 105 | subject.extra_attributes["first_name"].should == "Jack" 106 | end 107 | 108 | it "sets the value of JSON attributes containing Arrays to their parsed value" do 109 | subject.extra_attributes["foo_data"][0]["id"].should == 10529 110 | end 111 | 112 | it "sets the value of JSON attributes containing Hashes to their parsed value" do 113 | subject.extra_attributes["food_data"]["id"].should == 10529 114 | end 115 | 116 | it "sets non-hash attributes as strings" do 117 | subject.extra_attributes["last_name"].should be_a_kind_of String 118 | end 119 | 120 | it "sets the value of attributes which are not valid JSON but are valid YAML to their literal value" do 121 | subject.extra_attributes["allegedly_yaml"].should == '- 10' 122 | end 123 | end 124 | 125 | context "When parsing extra attributes from xml attributes" do 126 | let(:response_text) do 127 | < 129 | 130 | 131 | myuser 132 | 133 | 134 | 135 | 136 | 137 | RESPONSE_TEXT 138 | end 139 | 140 | subject { CASClient::ValidationResponse.new response_text } 141 | 142 | it "sets attributes for other type of format" do 143 | expected = {"username" => "myuser", "name" => 'My User', "email" => 'myuser@mail.example.com'} 144 | subject.user.should == 'myuser' 145 | subject.extra_attributes.should == expected 146 | end 147 | end 148 | end 149 | -------------------------------------------------------------------------------- /spec/database.yml: -------------------------------------------------------------------------------- 1 | test: 2 | adapter: sqlite3 3 | database: spec/test.sqlite3.db 4 | 5 | testjruby: 6 | adapter: jdbcsqlite3 7 | database: spec/test.sqlite3.db 8 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler.setup(:default, :development) 3 | require 'simplecov' unless ENV['TRAVIS'] || defined?(JRUBY_VERSION) 4 | Bundler.require 5 | 6 | require 'rubycas-client' 7 | 8 | SPEC_TMP_DIR="spec/tmp" 9 | 10 | Dir["./spec/support/**/*.rb"].each do |f| 11 | require f.gsub('.rb','') unless f.end_with? '_spec.rb' 12 | end 13 | 14 | require 'database_cleaner' 15 | 16 | RSpec.configure do |config| 17 | config.mock_with :rspec 18 | config.mock_framework = :rspec 19 | config.include ActionControllerHelpers 20 | 21 | config.treat_symbols_as_metadata_keys_with_true_values = true 22 | config.filter_run_including :focus 23 | config.run_all_when_everything_filtered = true 24 | config.fail_fast = false 25 | 26 | config.before(:suite) do 27 | ActiveRecordHelpers.setup_active_record 28 | DatabaseCleaner.strategy = :transaction 29 | DatabaseCleaner.clean_with(:truncation) 30 | end 31 | 32 | config.after(:suite) do 33 | ActiveRecordHelpers.teardown_active_record 34 | end 35 | 36 | config.before(:each) do 37 | DatabaseCleaner.start 38 | end 39 | 40 | config.after(:each) do 41 | DatabaseCleaner.clean 42 | end 43 | end 44 | 45 | -------------------------------------------------------------------------------- /spec/support/action_controller_helpers.rb: -------------------------------------------------------------------------------- 1 | require 'action_pack' 2 | 3 | module ActionControllerHelpers 4 | 5 | def mock_controller_with_session(request = nil, session={}) 6 | 7 | query_parameters = {:ticket => "bogusticket", :renew => false} 8 | parameters = query_parameters.dup 9 | 10 | #TODO this really need to be replaced with a "real" rails controller 11 | request ||= mock_post_request 12 | request.stub(:query_parameters) {query_parameters} 13 | request.stub(:path_parameters) {{}} 14 | controller = double("Controller") 15 | controller.stub(:session) {session} 16 | controller.stub(:request) {request} 17 | controller.stub(:url_for) {"bogusurl"} 18 | controller.stub(:query_parameters) {query_parameters} 19 | controller.stub(:path_parameters) {{}} 20 | controller.stub(:parameters) {parameters} 21 | controller.stub(:params) {parameters} 22 | controller 23 | end 24 | 25 | def mock_post_request 26 | mock_request = double("request") 27 | mock_request.stub(:post?) {true} 28 | mock_request.stub(:session_options) { Hash.new } 29 | mock_request.stub(:headers) { Hash.new } 30 | mock_request 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/support/active_record_helpers.rb: -------------------------------------------------------------------------------- 1 | require 'active_record' 2 | 3 | module ActiveRecordHelpers 4 | 5 | class << self 6 | def setup_active_record 7 | config_file = File.open("spec/database.yml") 8 | db_config = HashWithIndifferentAccess.new(YAML.load(config_file)) 9 | ActiveRecord::Base.establish_connection(db_config[(RUBY_PLATFORM == "java") ? :testjruby : :test]) 10 | ActiveRecord::Migration.verbose = false 11 | RubyCasTables.migrate(:up) 12 | end 13 | 14 | def teardown_active_record 15 | ActiveRecord::Migration.verbose = false 16 | RubyCasTables.migrate(:down) 17 | end 18 | end 19 | 20 | class RubyCasTables < ActiveRecord::Migration 21 | def self.up 22 | #default rails sessions table 23 | create_table :sessions do |t| 24 | t.string :session_id, :null => false 25 | t.text :data 26 | t.timestamps 27 | end 28 | add_index :sessions, :session_id 29 | add_index :sessions, :updated_at 30 | 31 | #column added to sessions table by rubycas-client 32 | add_column :sessions, :service_ticket, :string 33 | add_index :sessions, :service_ticket 34 | 35 | # pgtious table 36 | create_table :cas_pgtious do |t| 37 | t.string :pgt_iou, :null => false 38 | t.string :pgt_id, :null => false 39 | t.timestamps 40 | end 41 | end 42 | 43 | def self.down 44 | drop_table :sessions 45 | drop_table :cas_pgtious 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /spec/support/local_hash_ticket_store.rb: -------------------------------------------------------------------------------- 1 | require 'casclient/tickets/storage' 2 | 3 | class LocalHashTicketStore < CASClient::Tickets::Storage::AbstractTicketStore 4 | 5 | attr_accessor :st_hash 6 | attr_accessor :pgt_hash 7 | 8 | def store_service_session_lookup(st, controller) 9 | raise CASClient::CASException, "No service_ticket specified." if st.nil? 10 | raise CASClient::CASException, "No controller specified." if controller.nil? 11 | session_id = session_id_from_controller(controller) 12 | st = st.ticket if st.kind_of? CASClient::ServiceTicket 13 | st_hash[st] = session_id 14 | end 15 | 16 | def read_service_session_lookup(st) 17 | raise CASClient::CASException, "No service_ticket specified." if st.nil? 18 | st = st.ticket if st.kind_of? CASClient::ServiceTicket 19 | st_hash[st] 20 | end 21 | 22 | def cleanup_service_session_lookup(st) 23 | raise CASClient::CASException, "No service_ticket specified." if st.nil? 24 | st = st.ticket if st.kind_of? CASClient::ServiceTicket 25 | st_hash.delete(st) 26 | end 27 | 28 | def save_pgt_iou(pgt_iou, pgt) 29 | raise CASClient::CASException.new("Invalid pgt_iou") if pgt_iou.nil? 30 | raise CASClient::CASException.new("Invalid pgt") if pgt.nil? 31 | pgt_hash[pgt_iou] = pgt 32 | end 33 | 34 | def retrieve_pgt(pgt_iou) 35 | pgt = pgt_hash.delete(pgt_iou) 36 | raise CASClient::CASException.new("Invalid pgt_iou") if pgt.nil? 37 | pgt 38 | end 39 | 40 | def pgt_hash 41 | @pgt_hash ||= {} 42 | end 43 | 44 | def st_hash 45 | @pgt_hash ||= {} 46 | end 47 | 48 | end 49 | -------------------------------------------------------------------------------- /spec/support/local_hash_ticket_store_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe LocalHashTicketStore do 4 | it_should_behave_like "a ticket store" 5 | end 6 | -------------------------------------------------------------------------------- /spec/support/shared_examples_for_ticket_stores.rb: -------------------------------------------------------------------------------- 1 | shared_examples "a ticket store interacting with sessions" do 2 | describe "#store_service_session_lookup" do 3 | it "should raise CASException if the Service Ticket is nil" do 4 | expect { subject.store_service_session_lookup(nil, "controller") }.to raise_exception(CASClient::CASException, /No service_ticket specified/) 5 | end 6 | it "should raise CASException if the controller is nil" do 7 | expect { subject.store_service_session_lookup("service_ticket", nil) }.to raise_exception(CASClient::CASException, /No controller specified/) 8 | end 9 | it "should store the ticket without any errors" do 10 | expect { subject.store_service_session_lookup(service_ticket, mock_controller_with_session(nil, session)) }.to_not raise_exception 11 | end 12 | end 13 | 14 | describe "#get_session_for_service_ticket" do 15 | context "the service ticket is nil" do 16 | it "should raise CASException" do 17 | expect { subject.get_session_for_service_ticket(nil) }.to raise_exception(CASClient::CASException, /No service_ticket specified/) 18 | end 19 | end 20 | context "the service ticket is associated with a session" do 21 | before do 22 | subject.store_service_session_lookup(service_ticket, mock_controller_with_session(nil, session)) 23 | session.save! 24 | end 25 | it "should return the session_id and session for the given service ticket" do 26 | result_session_id, result_session = subject.get_session_for_service_ticket(service_ticket) 27 | result_session_id.should == session.session_id 28 | result_session.session_id.should == session.session_id 29 | result_session.data.should == session.data 30 | end 31 | end 32 | context "the service ticket is not associated with a session" do 33 | it "should return nils if there is no session for the given service ticket" do 34 | subject.get_session_for_service_ticket(service_ticket).should == [nil, nil] 35 | end 36 | end 37 | end 38 | 39 | describe "#process_single_sign_out" do 40 | context "the service ticket is nil" do 41 | it "should raise CASException" do 42 | expect { subject.process_single_sign_out(nil) }.to raise_exception(CASClient::CASException, /No service_ticket specified/) 43 | end 44 | end 45 | context "the service ticket is associated with a session" do 46 | before do 47 | subject.store_service_session_lookup(service_ticket, mock_controller_with_session(nil, session)) 48 | session.save! 49 | subject.process_single_sign_out(service_ticket) 50 | end 51 | context "the session" do 52 | it "should be destroyed" do 53 | ActiveRecord::SessionStore.session_class.find(:first, :conditions => {:session_id => session.session_id}).should be_nil 54 | end 55 | end 56 | it "should destroy session for the given service ticket" do 57 | subject.process_single_sign_out(service_ticket) 58 | end 59 | end 60 | context "the service ticket is not associated with a session" do 61 | it "should run without error if there is no session for the given service ticket" do 62 | expect { subject.process_single_sign_out(service_ticket) }.to_not raise_error 63 | end 64 | end 65 | end 66 | 67 | describe "#cleanup_service_session_lookup" do 68 | context "the service ticket is nil" do 69 | it "should raise CASException" do 70 | expect { subject.cleanup_service_session_lookup(nil) }.to raise_exception(CASClient::CASException, /No service_ticket specified/) 71 | end 72 | end 73 | it "should run without error" do 74 | expect { subject.cleanup_service_session_lookup(service_ticket) }.to_not raise_exception 75 | end 76 | end 77 | end 78 | 79 | shared_examples "a ticket store" do 80 | let(:ticket_store) { described_class.new } 81 | let(:service_url) { "https://www.example.com/cas" } 82 | let(:session) do 83 | ActiveRecord::SessionStore::Session.create!(:session_id => "session#{rand(1000)}", :data => {}) 84 | end 85 | subject { ticket_store } 86 | 87 | context "when dealing with sessions, Service Tickets, and Single Sign Out" do 88 | context "and the service ticket is a String" do 89 | it_behaves_like "a ticket store interacting with sessions" do 90 | let(:service_ticket) { "ST-ABC#{rand(1000)}" } 91 | end 92 | end 93 | context "and the service ticket is a ServiceTicket" do 94 | it_behaves_like "a ticket store interacting with sessions" do 95 | let(:service_ticket) { CASClient::ServiceTicket.new("ST-ABC#{rand(1000)}", service_url) } 96 | end 97 | end 98 | context "and the service ticket is a ProxyTicket" do 99 | it_behaves_like "a ticket store interacting with sessions" do 100 | let(:service_ticket) { CASClient::ProxyTicket.new("ST-ABC#{rand(1000)}", service_url) } 101 | end 102 | end 103 | end 104 | 105 | context "when dealing with Proxy Granting Tickets and their IOUs" do 106 | let(:pgt) { "my_pgt_#{rand(1000)}" } 107 | let(:pgt_iou) { "my_pgt_iou_#{rand(1000)}" } 108 | 109 | describe "#save_pgt_iou" do 110 | it "should raise CASClient::CASException if the pgt_iou is nil" do 111 | expect { subject.save_pgt_iou(nil, pgt) }.to raise_exception(CASClient::CASException, /Invalid pgt_iou/) 112 | end 113 | it "should raise CASClient::CASException if the pgt is nil" do 114 | expect { subject.save_pgt_iou(pgt_iou, nil) }.to raise_exception(CASClient::CASException, /Invalid pgt/) 115 | end 116 | end 117 | 118 | describe "#retrieve_pgt" do 119 | before do 120 | subject.save_pgt_iou(pgt_iou, pgt) 121 | end 122 | 123 | it "should return the stored pgt" do 124 | subject.retrieve_pgt(pgt_iou).should == pgt 125 | end 126 | 127 | it "should raise CASClient::CASException if the pgt_iou isn't in the store" do 128 | expect { subject.retrieve_pgt("not_my"+pgt_iou) }.to raise_exception(CASClient::CASException, /Invalid pgt_iou/) 129 | end 130 | 131 | it "should not return the stored pgt a second time" do 132 | subject.retrieve_pgt(pgt_iou).should == pgt 133 | expect { subject.retrieve_pgt(pgt_iou) }.to raise_exception(CASClient::CASException, /Invalid pgt_iou/) 134 | end 135 | end 136 | end 137 | end 138 | --------------------------------------------------------------------------------