From 5b431ef50a334a0367c706e6bbe5b034d479508c Mon Sep 17 00:00:00 2001 From: Erik Ordway Date: Tue, 29 Dec 2009 12:22:44 -0800 Subject: [PATCH] This allows CAS to work side by side with other Auth methods. This is at least one issue with this to logout of CAS you need session information but the logout method blows this away so I do the cas log out before the session is killed so the session persistest in rails. Because I needed to move the CAS before filters into login_cas and out of the application to make it work side by side. The user will still be logined into tracks even though their CAS session is closed as the session will still be there. def logout @user.forget_me if logged_in? cookies.delete :auth_token session['user_id'] = nil if ( SITE_CONFIG['authentication_schemes'].include? 'cas') && session[:cas_user] CASClient::Frameworks::Rails::Filter.logout(self) else reset_session notify :notice, "You have been logged out of Tracks." redirect_to_login end end The other issue I have with this is that: I could not find a use case for having mixed auth when using CAS. The reason to move to CAS is that all your users use CAS all the time. Even for admin accounts. Moodle is a good example of this in that when you activate CAS the default is that you can now only access moodle via CAS. By allowing mixed auth and self signup you end up with a anyone (the public) being able to sign up for accounts. --- app/controllers/application_controller.rb | 24 ++++---- app/controllers/login_controller.rb | 68 +++++++++++++++-------- app/controllers/users_controller.rb | 18 ++++-- app/models/user.rb | 2 +- app/views/layouts/standard.html.erb | 2 +- app/views/login/login.html.erb | 33 ++++++++--- app/views/users/new.html.erb | 9 ++- config/routes.rb | 1 + config/site.yml.tmpl | 4 ++ lib/tracks/config.rb | 8 +++ 10 files changed, 113 insertions(+), 56 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 85478213..fb4ee359 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -29,19 +29,7 @@ class ApplicationController < ActionController::Base layout proc{ |controller| controller.mobile? ? "mobile" : "standard" } exempt_from_layout /\.js\.erb$/ - if ( SITE_CONFIG['authentication_schemes'].include? 'cas') - # This will allow the user to view the index page without authentication - # but will process CAS authentication data if the user already - # has an SSO session open. - if (CASClient rescue nil) - # Only require sub-library if gem is installed and loaded - require 'casclient/frameworks/rails/filter' - before_filter CASClient::Frameworks::Rails::GatewayFilter, :only => :login - - # This requires the user to be authenticated for viewing all other pages. - before_filter CASClient::Frameworks::Rails::Filter, :except => [:login , :calendar] - end - end + before_filter :set_session_expiration before_filter :set_time_zone before_filter :set_zindex_counter @@ -238,6 +226,14 @@ class ApplicationController < ActionController::Base self.class.cas_enabled? end + def self.prefered_auth? + Tracks::Config.prefered_auth? + end + + def prefered_auth? + self.class.prefered_auth? + end + private def parse_date_per_user_prefs( s ) @@ -280,6 +276,8 @@ class ApplicationController < ActionController::Base def set_time_zone Time.zone = current_user.prefs.time_zone if logged_in? + locale = params[:locale] || 'en-US' + I18n.locale = locale end def set_zindex_counter diff --git a/app/controllers/login_controller.rb b/app/controllers/login_controller.rb index 53d57196..b2198a7c 100644 --- a/app/controllers/login_controller.rb +++ b/app/controllers/login_controller.rb @@ -6,6 +6,19 @@ class LoginController < ApplicationController skip_before_filter :login_required before_filter :login_optional before_filter :get_current_user + if ( SITE_CONFIG['authentication_schemes'].include? 'cas') + # This will allow the user to view the index page without authentication + # but will process CAS authentication data if the user already + # has an SSO session open. + if (CASClient rescue nil) + # Only require sub-library if gem is installed and loaded + require 'casclient/frameworks/rails/filter' + before_filter CASClient::Frameworks::Rails::GatewayFilter, :only => :login_cas + + # This requires the user to be authenticated for viewing all other pages. + before_filter CASClient::Frameworks::Rails::Filter, :only => [:login_cas ] + end + end def login if cas_enabled? @@ -18,6 +31,7 @@ class LoginController < ApplicationController login_cas else @page_title = "TRACKS::Login" + cookies[:preferred_auth] = prefered_auth? unless cookies[:preferred_auth] case request.method when :post if @user = User.authenticate(params['user_login'], params['user_password']) @@ -55,10 +69,10 @@ class LoginController < ApplicationController @user.forget_me if logged_in? cookies.delete :auth_token session['user_id'] = nil - reset_session - if ( SITE_CONFIG['authentication_schemes'].include? 'cas') + if ( SITE_CONFIG['authentication_schemes'].include? 'cas') && session[:cas_user] CASClient::Frameworks::Rails::Filter.logout(self) else + reset_session notify :notice, "You have been logged out of Tracks." redirect_to_login end @@ -83,6 +97,33 @@ class LoginController < ApplicationController respond_to do |format| format.js end + end + + def login_cas + # If checkbox on login page checked, we don't expire the session after 1 hour + # of inactivity and we remember this user for future browser sessions + + session['noexpiry'] ||= params['user_noexpiry'] + if session[:cas_user] + if @user = User.find_by_login(session[:cas_user]) + session['user_id'] = @user.id + msg = (should_expire_sessions?) ? "will expire after 1 hour of inactivity." : "will not expire." + notify :notice, "Login successful: session #{msg}" + cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => SITE_CONFIG['secure_cookies'] } + unless should_expire_sessions? + @user.remember_me + cookies[:auth_token] = { :value => @user.remember_token, :expires => @user.remember_token_expires_at, :secure => SITE_CONFIG['secure_cookies'] } + end + #redirect_back_or_home + else + notify :warning, "Sorry, no user by that CAS username exists (#{session[:cas_user]})" + redirect_to signup_url ; return + end + else + notify :warning, result.message + end + redirect_back_or_home + end private @@ -125,26 +166,5 @@ class LoginController < ApplicationController end end - def login_cas - # If checkbox on login page checked, we don't expire the session after 1 hour - # of inactivity and we remember this user for future browser sessions - session['noexpiry'] ||= params['user_noexpiry'] - if session[:cas_user] - if @user = User.find_by_login(session[:cas_user]) - session['user_id'] = @user.id - msg = (should_expire_sessions?) ? "will expire after 1 hour of inactivity." : "will not expire." - notify :notice, "Login successful: session #{msg}" - cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => SITE_CONFIG['secure_cookies'] } - unless should_expire_sessions? - @user.remember_me - cookies[:auth_token] = { :value => @user.remember_token, :expires => @user.remember_token_expires_at, :secure => SITE_CONFIG['secure_cookies'] } - end - redirect_back_or_home - else - notify :warning, "Sorry, no user by that CAS username exists (#{session[:cas_user]})" - end - else - notify :warning, result.message - end - end + end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 45caef51..5aa985ba 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -27,6 +27,13 @@ class UsersController < ApplicationController # GET /users/new def new + @auth_types = [] + unless session[:cas_user] + Tracks::Config.auth_schemes.each {|auth| @auth_types << [auth,auth]} + else + @auth_types << ['cas','cas'] + end + if User.no_users_yet? @page_title = "TRACKS::Sign up as the admin user" @heading = "Welcome to TRACKS. To get started, please create an admin account:" @@ -68,7 +75,9 @@ class UsersController < ApplicationController user = User.new(params['user']) if Tracks::Config.auth_schemes.include?('cas') - user.auth_type = "cas" #since CAS will be doing all the auth we may as well set it for everyone when CAS in enabled + if user.auth_type.eql? "cas" + user.crypted_password = "cas" + end end unless user.valid? @@ -79,9 +88,6 @@ class UsersController < ApplicationController first_user_signing_up = User.no_users_yet? user.is_admin = true if first_user_signing_up - if Tracks::Config.auth_schemes.include?('cas') - user.auth_type = "cas" #since CAS will be doing all the auth we may as well set it for everyone when CAS in enabled - end if user.save @user = User.authenticate(user.login, params['user']['password']) @user.create_preference @@ -102,8 +108,8 @@ class UsersController < ApplicationController return end user = User.new(params[:request]) - if Tracks::Config.auth_schemes.include?('cas') - user.auth_type = "cas" #since CAS will be doing all the auth we may as well set it for everyone when CAS in enabled + if Tracks::Config.auth_schemes.include?('cas') && session[:cas_user] + user.auth_type = "cas" #if they area cas user end user.password_confirmation = params[:request][:password] if user.save diff --git a/app/models/user.rb b/app/models/user.rb index 2dd6f6de..068c0cb3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -153,7 +153,7 @@ class User < ActiveRecord::Base if Tracks::Config.auth_schemes.include?('ldap') return candidate if candidate.auth_type == 'ldap' && SimpleLdapAuthenticator.valid?(login, pass) end - if Tracks::Config.auth_schemes.include?('cas') + if Tracks::Config.auth_schemes.include?('cas') && candidate.auth_type.eql?("cas") return candidate #because we can not auth them with out thier real password we have to settle for this end return nil diff --git a/app/views/layouts/standard.html.erb b/app/views/layouts/standard.html.erb index f383cd42..51d0570b 100644 --- a/app/views/layouts/standard.html.erb +++ b/app/views/layouts/standard.html.erb @@ -54,7 +54,7 @@