diff --git a/lib/omniauth/strategies/cas.rb b/lib/omniauth/strategies/cas.rb index d4bc18e89ce8c0683c6368e693999b40a30caf30..e6c1f652dc4ecb087ec0ebee016667e8b84873d4 100644 --- a/lib/omniauth/strategies/cas.rb +++ b/lib/omniauth/strategies/cas.rb @@ -9,6 +9,9 @@ module OmniAuth autoload :Configuration, 'omniauth/strategies/cas/configuration' autoload :ServiceTicketValidator, 'omniauth/strategies/cas/service_ticket_validator' + attr_accessor :raw_info + alias_method :user_info, :raw_info + option :name, :cas # TODO: Why do I need to specify this? option :host, nil @@ -17,6 +20,35 @@ module OmniAuth option :service_validate_url, '/serviceValidate' option :login_url, '/login' option :logout_url, '/logout' + option :uid_key, 'user' + + # As required by https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema + AuthHashSchemaKeys = %w{name email first_name last_name location image phone} + info do + prune!({ + :name => raw_info['name'], + :email => raw_info['email'], + :first_name => raw_info['first_name'], + :last_name => raw_info['last_name'], + :location => raw_info['location'], + :image => raw_info['image'], + :phone => raw_info['phone'] + }) + end + + extra do + prune! raw_info.delete_if{ |k,v| AuthHashSchemaKeys.include?(k) } + end + + uid do + raw_info[ @options[:uid_key].to_s ] + end + + credentials do + prune!({ + :ticket => @ticket + }) + end def initialize( app, *args, &block ) super @@ -24,23 +56,17 @@ module OmniAuth end def callback_phase - ticket = request.params['ticket'] + @ticket = request.params['ticket'] - return fail!(:no_ticket, 'No CAS Ticket') unless ticket + return fail!(:no_ticket, 'No CAS Ticket') unless @ticket - validator = ServiceTicketValidator.new(self, @options, callback_url, ticket) - @user_info = validator.user_info + self.raw_info = ServiceTicketValidator.new(self, @options, callback_url, @ticket).user_info - return fail!(:invalid_ticket, 'Invalid CAS Ticket') if @user_info.nil? or @user_info.empty? + return fail!(:invalid_ticket, 'Invalid CAS Ticket') if raw_info.empty? super end - # TODO: Refactor this like omniauth-identity - # TODO: What's the intention of these? Diff between info and extra? - extra { @user_info } - uid { @user_info['user'] } - def request_phase [ 302, @@ -101,6 +127,16 @@ module OmniAuth end.to_s end + private + + # Deletes Hash pairs with `nil` values. + # From https://github.com/mkdynamic/omniauth-facebook/blob/972ed5e3456bcaed7df1f55efd7c05c216c8f48e/lib/omniauth/strategies/facebook.rb#L122-127 + def prune!(hash) + hash.delete_if do |_, value| + prune!(value) if value.is_a?(Hash) + value.nil? || (value.respond_to?(:empty?) && value.empty?) + end + end # def cas_url( path ) # "#{cas_protocol}://#{@options.host}#{@options.port}#{path}" diff --git a/spec/fixtures/cas_success.xml b/spec/fixtures/cas_success.xml index 5a621ff2445478605280dba83a0cfb0ab2a9c2e1..18904f64b35a3d7ffb16eec0d5bb66120457d1f6 100644 --- a/spec/fixtures/cas_success.xml +++ b/spec/fixtures/cas_success.xml @@ -1,8 +1,14 @@ <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'> <cas:authenticationSuccess> <cas:user>psegel</cas:user> - <cas:first-name>Peter</cas:first-name> - <cas:last-name>Segel</cas:last-name> - <hire-date>2004-07-13</hire-date> + <cas:employeeid>54</cas:employeeid> + <cas:first_name>P. Segel</cas:first_name> + <cas:first_name>Peter</cas:first_name> + <cas:last_name>Segel</cas:last_name> + <cas:email>psegel@intridea.com</cas:email> + <cas:location>Washington, D.C.</cas:location> + <cas:image>/images/user.jpg</cas:image> + <cas:phone>555-555-5555</cas:phone> + <cas:hire_date>2004-07-13</cas:hire_date> </cas:authenticationSuccess> </cas:serviceResponse> diff --git a/spec/omniauth/strategies/cas_spec.rb b/spec/omniauth/strategies/cas_spec.rb index cef4e6a0984d716912b7ea99c7361441411a2ff1..7f815243cff09fede0c5152d46293b168ed49f1b 100644 --- a/spec/omniauth/strategies/cas_spec.rb +++ b/spec/omniauth/strategies/cas_spec.rb @@ -7,7 +7,7 @@ describe OmniAuth::Strategies::CAS, :type => :strategy do def app Rack::Builder.new { use OmniAuth::Test::PhonySession - use MyCasProvider, :name => :cas, :host => 'cas.example.org' + use MyCasProvider, :name => :cas, :host => 'cas.example.org', :uid_key => :employeeid run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [env.key?('omniauth.auth').to_s]] } }.to_app end @@ -70,14 +70,30 @@ describe OmniAuth::Strategies::CAS, :type => :strategy do subject { last_request.env['omniauth.auth'] } it { should be_kind_of Hash } its(:provider) { should == :cas } - its(:uid) { should == 'psegel'} - - context "['extra']" do + its(:uid) { should == '54'} + + context "the info hash" do + subject { last_request.env['omniauth.auth']['info'] } + it { should have(6).items } + its('name') { should == 'Peter Segel' } + its('first_name') { should == 'Peter' } + its('last_name') { should == 'Segel' } + its('email') { should == 'psegel@intridea.com' } + its('location') { should == 'Washington, D.C.' } + its('image') { should == '/images/user.jpg' } + its('phone') { should == '555-555-5555' } + end + context "the extra hash" do subject { last_request.env['omniauth.auth']['extra'] } - it { should be_kind_of Hash } - its('first-name') { should == 'Peter' } - its('last-name') { should == 'Segel' } - its('hire-date') { should == '2004-07-13' } + it { should have(3).items } + its('user') { should == 'psegel' } + its('employeeid') { should == '54' } + its('hire_date') { should == '2004-07-13' } + end + context "the credentials hash" do + subject { last_request.env['omniauth.auth']['credentials'] } + it { should have(1).items } + its('ticket') { should == '593af' } end end