From 18c74ac4aca9e98a55ab3f80f0d3618574f0d726 Mon Sep 17 00:00:00 2001 From: David Massad Date: Tue, 15 Sep 2015 11:20:28 -0500 Subject: [PATCH 01/13] fixed problem where verify_ssl_cert? was returning true when verify_ssl_cert was set to false --- lib/rack-cas/configuration.rb | 2 +- spec/rack-cas/configuration_spec.rb | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 spec/rack-cas/configuration_spec.rb diff --git a/lib/rack-cas/configuration.rb b/lib/rack-cas/configuration.rb index e8ce96c..788a584 100644 --- a/lib/rack-cas/configuration.rb +++ b/lib/rack-cas/configuration.rb @@ -6,7 +6,7 @@ class Configuration attr_accessor setting define_method "#{setting}?" do - !(send(setting).nil? || send(setting) == []) + !(send(setting).nil? || send(setting) == [] || send(setting) == false) end end diff --git a/spec/rack-cas/configuration_spec.rb b/spec/rack-cas/configuration_spec.rb new file mode 100644 index 0000000..9618d5e --- /dev/null +++ b/spec/rack-cas/configuration_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' +require 'rack-cas/configuration' + +describe RackCAS::Configuration do + + it 'returns true for attribute? if the attribute is neither nil, an empty array, nor false' do + configuration = RackCAS::Configuration.new + configuration.update(renew: true, verify_ssl_cert: true, server_url: 'https://cas.example.com/', exclude_paths: ['/api', /\.json/]) + expect(configuration.renew?).to be true + expect(configuration.verify_ssl_cert?).to be true + expect(configuration.server_url?).to be true + expect(configuration.exclude_paths?).to be true + end + + it 'returns false for attribute? if the attribute is either nil, an empty array, or false' do + configuration = RackCAS::Configuration.new + configuration.update(renew: nil, verify_ssl_cert: false, server_url: 'https://cas.example.com/', exclude_paths: []) + expect(configuration.renew?).to be false + expect(configuration.verify_ssl_cert?).to be false + expect(configuration.exclude_paths?).to be false + end + +end \ No newline at end of file From b399f492fc07e9c64f20f2c657cf337fd13480ff Mon Sep 17 00:00:00 2001 From: David Massad Date: Tue, 29 Sep 2015 12:59:36 -0500 Subject: [PATCH 02/13] added .rvmrc to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2a7b3b6..f1581a1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .rspec Gemfile.lock pkg/* +.rvmrc \ No newline at end of file From 186790864dc2e23392365b8ff61a83d542cfdab7 Mon Sep 17 00:00:00 2001 From: David Massad Date: Tue, 29 Sep 2015 13:38:23 -0500 Subject: [PATCH 03/13] Implemented proxy support --- ...ranting_ticket_ious_migration_generator.rb | 26 +++++++ ...as_proxy_granting_ticket_ious_migration.rb | 17 ++++ lib/rack-cas/cas_request.rb | 35 ++++++++- lib/rack-cas/configuration.rb | 2 +- lib/rack-cas/proxy_response.rb | 77 +++++++++++++++++++ lib/rack-cas/proxy_ticket_generator.rb | 24 ++++++ lib/rack-cas/server.rb | 23 ++++-- lib/rack-cas/service_validation_response.rb | 6 ++ lib/rack-cas/session_store/active_record.rb | 13 ++++ lib/rack-cas/session_store/mongoid.rb | 22 ++++++ lib/rack/cas.rb | 20 ++++- spec/fixtures/jasig_service_response.xml | 1 + spec/fixtures/rubycas_service_response.xml | 1 + spec/rack-cas/cas_request_spec.rb | 4 +- spec/rack-cas/server_spec.rb | 14 +++- 15 files changed, 267 insertions(+), 18 deletions(-) create mode 100644 lib/generators/proxy_granting_ticket_ious_migration_generator.rb create mode 100644 lib/generators/templates/create_rack_cas_proxy_granting_ticket_ious_migration.rb create mode 100644 lib/rack-cas/proxy_response.rb create mode 100644 lib/rack-cas/proxy_ticket_generator.rb diff --git a/lib/generators/proxy_granting_ticket_ious_migration_generator.rb b/lib/generators/proxy_granting_ticket_ious_migration_generator.rb new file mode 100644 index 0000000..a789e26 --- /dev/null +++ b/lib/generators/proxy_granting_ticket_ious_migration_generator.rb @@ -0,0 +1,26 @@ +require 'rails/generators' +require 'rails/generators/migration' + +class ProxyGrantingTicketIousMigrationGenerator < Rails::Generators::Base + include Rails::Generators::Migration + + desc 'Creates a new Proxy Granting Ticket IOUs migration file' + + def self.source_root + File.expand_path('../templates', __FILE__) + end + + def self.next_migration_number(dirname) + if ActiveRecord::Base.timestamped_migrations + migration_number = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i + migration_number += 1 + migration_number.to_s + else + "%.3d" % (current_migration_number(dirname) + 1) + end + end + + def create_migration_file + migration_template 'create_rack_cas_proxy_granting_ticket_ious_migration.rb', 'db/migrate/create_rack_cas_proxy_granting_ticket_ious.rb' + end +end diff --git a/lib/generators/templates/create_rack_cas_proxy_granting_ticket_ious_migration.rb b/lib/generators/templates/create_rack_cas_proxy_granting_ticket_ious_migration.rb new file mode 100644 index 0000000..97275d2 --- /dev/null +++ b/lib/generators/templates/create_rack_cas_proxy_granting_ticket_ious_migration.rb @@ -0,0 +1,17 @@ +class CreateRackCasProxyGrantingTicketIous < ActiveRecord::Migration + def self.up + create_table :proxy_granting_ticket_ious do |t| + t.string :proxy_granting_ticket_iou, :null => false + t.string :proxy_granting_ticket, :null => false + t.timestamps + end + + add_index :proxy_granting_ticket_ious, :proxy_granting_ticket_iou + add_index :proxy_granting_ticket_ious, :proxy_granting_ticket + add_index :proxy_granting_ticket_ious, :updated_at + end + + def self.down + drop_table :proxy_granting_ticket_ious + end +end \ No newline at end of file diff --git a/lib/rack-cas/cas_request.rb b/lib/rack-cas/cas_request.rb index 1484cbd..4ea0fcd 100644 --- a/lib/rack-cas/cas_request.rb +++ b/lib/rack-cas/cas_request.rb @@ -1,3 +1,4 @@ +require 'addressable/uri' require 'nokogiri' class CASRequest @@ -27,10 +28,15 @@ def single_sign_out? def ticket_validation? # The CAS protocol specifies that services must support tickets of - # *up to* 32 characters in length (including ST-), and recommendes + # *up to* 32 characters in length (including ST-), and recommends # that services accept tickets up to 256 characters long. - # http://www.jasig.org/cas/protocol - !!(@request.get? && ticket_param && ticket_param.to_s =~ /\AST\-[^\s]{1,253}\Z/) + # + # It also specifies that although the service ticket MUST start with "ST-", + # the proxy ticket SHOULD start with "PT-". The "ST-" validation has + # been moved to the validate_service_url method in server.rb. + # + # http://jasig.github.io/cas/development/protocol/CAS-Protocol-Specification.html + !!(@request.get? && ticket_param && ticket_param.to_s =~ /\A[^\s]{1,256}\Z/) end def path_matches?(strings_or_regexps) @@ -43,12 +49,35 @@ def path_matches?(strings_or_regexps) end end + def pgt_callback? + !!(@request.get? && RackCAS.config.pgt_callback_url? && \ + Addressable::URI.parse(RackCAS.config.pgt_callback_url).path == Addressable::URI.parse(@request.url).path && \ + pgt_iou_param && pgt_iou_param.to_s =~ /\A[^\s]{1,256}\Z/ && \ + pgt_param && pgt_param.to_s =~ /\A[^\s]{1,256}\Z/) + end + + def pgt + pgt_param if pgt_callback? + end + + def pgt_iou + pgt_iou_param if pgt_callback? + end + private def ticket_param @request.params['ticket'] end + def pgt_iou_param + @request.params['pgtIou'] + end + + def pgt_param + @request.params['pgtId'] + end + def sso_ticket xml = Nokogiri::XML(@request.params['logoutRequest']) node = xml.root.children.find { |c| c.name =~ /SessionIndex/i } diff --git a/lib/rack-cas/configuration.rb b/lib/rack-cas/configuration.rb index 788a584..02e4fad 100644 --- a/lib/rack-cas/configuration.rb +++ b/lib/rack-cas/configuration.rb @@ -1,6 +1,6 @@ module RackCAS class Configuration - SETTINGS = [:server_url, :session_store, :exclude_path, :exclude_paths, :extra_attributes_filter, :verify_ssl_cert, :renew, :use_saml_validation] + SETTINGS = [:server_url, :session_store, :exclude_path, :exclude_paths, :extra_attributes_filter, :verify_ssl_cert, :renew, :use_saml_validation, :pgt_callback_url] SETTINGS.each do |setting| attr_accessor setting diff --git a/lib/rack-cas/proxy_response.rb b/lib/rack-cas/proxy_response.rb new file mode 100644 index 0000000..5512d7b --- /dev/null +++ b/lib/rack-cas/proxy_response.rb @@ -0,0 +1,77 @@ +module RackCAS + class ProxyResponse + class ProxyFailure < StandardError; end + class RequestInvalidError < ProxyFailure; end + class UnauthorizedServiceError < ProxyFailure; end + class InternalError < ProxyFailure; end + + REQUEST_HEADERS = { 'Accept' => '*/*' } + + def initialize(url) + @url = URL.parse(url) + end + + def proxy_ticket + if success? + xml.xpath('/cas:serviceResponse/cas:proxySuccess/cas:proxyTicket').text + else + case failure_code + when 'INVALID_REQUEST' + raise RequestInvalidError, failure_message + when 'UNAUTHORIZED_SERVICE' + raise UnauthorizedServiceError, failure_message + when 'INTERNAL_ERROR' + raise InternalError, failure_message + else + raise ProxyFailure, failure_message + end + end + end + + protected + + def success? + @success ||= !!xml.at('/cas:serviceResponse/cas:proxySuccess') + end + + def proxy_failure + @proxy_failure ||= xml.at('/cas:serviceResponse/cas:proxyFailure') + end + + def failure_message + if proxy_failure + proxy_failure.text.strip + end + end + + def failure_code + if proxy_failure + proxy_failure['code'] + end + end + + def response + require 'net/http' + return @response unless @response.nil? + + http = Net::HTTP.new(@url.host, @url.inferred_port) + if @url.scheme == 'https' + http.use_ssl = true + http.verify_mode = RackCAS.config.verify_ssl_cert? ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE + end + + http.start do |conn| + @response = conn.get(@url.request_uri, REQUEST_HEADERS) + end + + @response + end + + def xml + return @xml unless @xml.nil? + + @xml = Nokogiri::XML(response.body) + end + + end +end \ No newline at end of file diff --git a/lib/rack-cas/proxy_ticket_generator.rb b/lib/rack-cas/proxy_ticket_generator.rb new file mode 100644 index 0000000..d7c03c6 --- /dev/null +++ b/lib/rack-cas/proxy_ticket_generator.rb @@ -0,0 +1,24 @@ +require 'rack-cas/url' +require 'rack-cas/proxy_response' + +module RackCAS + class ProxyTicketGenerator + + def self.generate(service_url, pgt) + response = ProxyResponse.new proxy_url(service_url, pgt) + response.proxy_ticket + end + + private + + def self.proxy_url(service_url, pgt) + service_url = URL.parse(service_url).remove_param('ticket').to_s + server_url = RackCAS::URL.parse(RackCAS.config.server_url) + server_url.dup.tap do |url| + url.append_path('proxy') + url.add_params(targetService: service_url, pgt: pgt) + end + end + + end +end \ No newline at end of file diff --git a/lib/rack-cas/server.rb b/lib/rack-cas/server.rb index b90bcd2..d6042dc 100644 --- a/lib/rack-cas/server.rb +++ b/lib/rack-cas/server.rb @@ -23,13 +23,17 @@ def logout_url(params = {}) end end - def validate_service(service_url, ticket) + def validate_service(service_url, ticket, pgt_url = RackCAS.config.pgt_callback_url) + pgt_iou = nil unless RackCAS.config.use_saml_validation? - response = ServiceValidationResponse.new validate_service_url(service_url, ticket) + response = ServiceValidationResponse.new validate_service_url(service_url, ticket, pgt_url) + if !!pgt_url + pgt_iou = response.proxy_granting_ticket_iou + end else response = SAMLValidationResponse.new saml_validate_url(service_url), ticket end - [response.user, response.extra_attributes] + [response.user, response.extra_attributes, pgt_iou] end protected @@ -39,9 +43,18 @@ def saml_validate_url(service_url) @url.dup.append_path('samlValidate').add_params(TARGET: service_url) end - def validate_service_url(service_url, ticket) + def validate_service_url(service_url, ticket, pgt_url = RackCAS.config.pgt_callback_url) service_url = URL.parse(service_url).remove_param('ticket').to_s - @url.dup.append_path('serviceValidate').add_params(service: service_url, ticket: ticket) + @url.dup.tap do |url| + if ticket =~ /\AST\-[^\s]{1,253}\Z/ + url.append_path('serviceValidate') + else + url.append_path('proxyValidate') + end + url.add_params(service: service_url, ticket: ticket) + url.add_params(pgtUrl: pgt_url) if pgt_url + end end + end end diff --git a/lib/rack-cas/service_validation_response.rb b/lib/rack-cas/service_validation_response.rb index 544b105..08c83ea 100644 --- a/lib/rack-cas/service_validation_response.rb +++ b/lib/rack-cas/service_validation_response.rb @@ -56,6 +56,12 @@ def extra_attributes attrs end + def proxy_granting_ticket_iou + if success? + @proxy_granting_ticket_iou ||= xml.at('/cas:serviceResponse/cas:authenticationSuccess/cas:proxyGrantingTicket').text + end + end + protected def success? diff --git a/lib/rack-cas/session_store/active_record.rb b/lib/rack-cas/session_store/active_record.rb index 95755db..f4468d3 100644 --- a/lib/rack-cas/session_store/active_record.rb +++ b/lib/rack-cas/session_store/active_record.rb @@ -1,8 +1,20 @@ module RackCAS module ActiveRecordStore + class ProxyGrantingTicketIou < ActiveRecord::Base + end + class Session < ActiveRecord::Base end + def self.create_proxy_granting_ticket(pgt_iou, pgt) + ProxyGrantingTicketIou.create!(proxy_granting_ticket_iou: pgt_iou, proxy_granting_ticket: pgt) + end + + def self.proxy_granting_ticket_for(pgt_iou) + proxy_granting_ticket_iou = ProxyGrantingTicketIou.where(proxy_granting_ticket_iou: pgt_iou).first || nil + proxy_granting_ticket_iou.proxy_granting_ticket if proxy_granting_ticket_iou + end + def self.destroy_session_by_cas_ticket(cas_ticket) affected = Session.delete_all(cas_ticket: cas_ticket) affected == 1 @@ -11,6 +23,7 @@ def self.destroy_session_by_cas_ticket(cas_ticket) def self.prune(after = nil) after ||= Time.now - 2592000 # 30 days ago Session.where('updated_at < ?', after).delete_all + ProxyGrantingTicketIou.where('updated_at < ?', after).delete_all end private diff --git a/lib/rack-cas/session_store/mongoid.rb b/lib/rack-cas/session_store/mongoid.rb index cec2b3b..392069b 100644 --- a/lib/rack-cas/session_store/mongoid.rb +++ b/lib/rack-cas/session_store/mongoid.rb @@ -1,5 +1,15 @@ module RackCAS module MongoidStore + + class ProxyGrantingTicketIou + include Mongoid::Document + include Mongoid::Timestamps + + field :_id, type: String + field :proxy_granting_ticket_iou, type: String + field :proxy_granting_ticket, type: String + end + class Session include Mongoid::Document include Mongoid::Timestamps @@ -15,6 +25,17 @@ class Session field :cas_ticket, type: String end + def self.create_proxy_granting_ticket(pgt_iou, pgt) + ProxyGrantingTicketIou.create!(proxy_granting_ticket_iou: pgt_iou, proxy_granting_ticket: pgt) + end + + def self.proxy_granting_ticket_for(pgt_iou = nil) + if pgt_iou + proxy_granting_ticket_iou = ProxyGrantingTicketIou.where(proxy_granting_ticket_iou: pgt_iou).first || nil + proxy_granting_ticket_iou.proxy_granting_ticket if proxy_granting_ticket_iou + end + end + def self.destroy_session_by_cas_ticket(cas_ticket) affected = Session.where(cas_ticket: cas_ticket).delete affected == 1 @@ -23,6 +44,7 @@ def self.destroy_session_by_cas_ticket(cas_ticket) def self.prune(after = nil) after ||= Time.now - 2592000 # 30 days ago Session.where(:updated_at.lte => after).delete + ProxyGrantingTicketIou.where(:updated_at.lte => after).delete end private diff --git a/lib/rack/cas.rb b/lib/rack/cas.rb index 7863618..2fd26da 100644 --- a/lib/rack/cas.rb +++ b/lib/rack/cas.rb @@ -24,17 +24,23 @@ def call(env) log env, 'rack-cas: Intercepting ticket validation request.' begin - user, extra_attrs = get_user(request.url, cas_request.ticket) + user, extra_attrs, pgt_iou = get_user(request.url, cas_request.ticket) rescue RackCAS::ServiceValidationResponse::TicketInvalidError, RackCAS::SAMLValidationResponse::TicketInvalidError log env, 'rack-cas: Invalid ticket. Redirecting to CAS login.' return redirect_to server.login_url(cas_request.service_url).to_s end - store_session request, user, cas_request.ticket, extra_attrs + store_session request, user, cas_request.ticket, extra_attrs, pgt_iou return redirect_to cas_request.service_url end + if cas_request.pgt_callback? + log env, 'rack-cas: Intercepting proxy granting ticket callback request.' + RackCAS.config.session_store.create_proxy_granting_ticket(cas_request.pgt_iou, cas_request.pgt) + return [200, {'Content-Type' => 'text/plain'}, ['CAS proxy granting ticket created successfully.']] + end + if cas_request.logout? log env, 'rack-cas: Intercepting logout request.' @@ -67,15 +73,21 @@ def server end def get_user(service_url, ticket) - server.validate_service(service_url, ticket) + server.validate_service(service_url, ticket, RackCAS.config.pgt_callback_url) end - def store_session(request, user, ticket, extra_attrs = {}) + def store_session(request, user, ticket, extra_attrs = {}, pgt_iou = nil) if RackCAS.config.extra_attributes_filter? extra_attrs.select! { |key, val| RackCAS.config.extra_attributes_filter.map(&:to_s).include? key.to_s } end request.session['cas'] = { 'user' => user, 'ticket' => ticket, 'extra_attributes' => extra_attrs } + + if pgt_iou + pgt = RackCAS.config.session_store.proxy_granting_ticket_for(pgt_iou) + request.session['cas']['pgt'] = pgt if pgt + end + end def redirect_to(url, status=302) diff --git a/spec/fixtures/jasig_service_response.xml b/spec/fixtures/jasig_service_response.xml index 95735de..4fecd16 100644 --- a/spec/fixtures/jasig_service_response.xml +++ b/spec/fixtures/jasig_service_response.xml @@ -14,5 +14,6 @@ employee CN=Testing,OU=Departments,DC=example,DC=com + PGTIOU-1234567890 \ No newline at end of file diff --git a/spec/fixtures/rubycas_service_response.xml b/spec/fixtures/rubycas_service_response.xml index 6d4abda..12f1181 100644 --- a/spec/fixtures/rubycas_service_response.xml +++ b/spec/fixtures/rubycas_service_response.xml @@ -58,5 +58,6 @@ - CN=Employees,OU=Security Groups,DC=example,DC=com ]]> + PGTIOU-1234567890 \ No newline at end of file diff --git a/spec/rack-cas/cas_request_spec.rb b/spec/rack-cas/cas_request_spec.rb index 63e2aa3..f8709e8 100644 --- a/spec/rack-cas/cas_request_spec.rb +++ b/spec/rack-cas/cas_request_spec.rb @@ -24,13 +24,13 @@ def app end context 'invalid ticket' do - before { get '/private/something?ticket=BLARG' } + before { get '/private/something?ticket=BL+ARG' } its(:ticket_validation?) { should be false } its(:ticket) { should be nil } end context 'short ticket' do - before { get '/private/something?ticket=ST-' } + before { get '/private/something?ticket=' } its(:ticket_validation?) { should be false } its(:ticket) { should be nil } end diff --git a/spec/rack-cas/server_spec.rb b/spec/rack-cas/server_spec.rb index bf9bf11..5a2edc7 100644 --- a/spec/rack-cas/server_spec.rb +++ b/spec/rack-cas/server_spec.rb @@ -42,11 +42,19 @@ end end - describe :validate_service do + describe :validate_service_without_pgt_url do subject { server.validate_service(service_url, ticket) } - its(:length) { should eql 2 } + its(:length) { should eql 3 } its(:first) { should eql 'johnd0' } - its(:last) { should be_kind_of Hash } + its(:last) { should be nil } + end + + describe :validate_service_with_pgt_url do + + subject { server.validate_service(service_url, ticket, 'http://example.com/callback') } + its(:length) { should eql 3 } + its(:first) { should eql 'johnd0' } + its(:last) { should_not be 'PGTIOU-1234567890' } end describe :validate_service_url do From 9f9abbbb0febbbfc713273d293c96855bb367c9a Mon Sep 17 00:00:00 2001 From: David Massad Date: Thu, 8 Oct 2015 07:48:07 -0500 Subject: [PATCH 04/13] fixed example in server_spec.rb --- spec/rack-cas/server_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/rack-cas/server_spec.rb b/spec/rack-cas/server_spec.rb index 5a2edc7..36c733d 100644 --- a/spec/rack-cas/server_spec.rb +++ b/spec/rack-cas/server_spec.rb @@ -54,7 +54,7 @@ subject { server.validate_service(service_url, ticket, 'http://example.com/callback') } its(:length) { should eql 3 } its(:first) { should eql 'johnd0' } - its(:last) { should_not be 'PGTIOU-1234567890' } + its(:last) { should eql 'PGTIOU-1234567890' } end describe :validate_service_url do From ee3e1ab2906ff7f79cd104f040b73057938b6f6e Mon Sep 17 00:00:00 2001 From: David Massad Date: Tue, 3 May 2016 21:42:24 -0500 Subject: [PATCH 05/13] Added require statement to prevent "uninitialized constant RackCAS::ProxyResponse::Nokogiri" error. --- lib/rack-cas/proxy_response.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rack-cas/proxy_response.rb b/lib/rack-cas/proxy_response.rb index 5512d7b..4001a16 100644 --- a/lib/rack-cas/proxy_response.rb +++ b/lib/rack-cas/proxy_response.rb @@ -1,3 +1,5 @@ +require 'nokogiri' + module RackCAS class ProxyResponse class ProxyFailure < StandardError; end From b8f86527daffa2ac821843373a8a231fb0d1efa9 Mon Sep 17 00:00:00 2001 From: David Massad Date: Tue, 3 May 2016 21:43:59 -0500 Subject: [PATCH 06/13] Updated .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f1581a1..2084270 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ .rspec Gemfile.lock pkg/* -.rvmrc \ No newline at end of file +.rvmrc +.idea \ No newline at end of file From 2a5c963f36d9c72f831647f4537c5378885692d6 Mon Sep 17 00:00:00 2001 From: David Massad Date: Tue, 30 Aug 2016 12:54:09 -0500 Subject: [PATCH 07/13] removed cas namespaces --- lib/rack-cas/proxy_response.rb | 6 +++--- lib/rack-cas/service_validation_response.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/rack-cas/proxy_response.rb b/lib/rack-cas/proxy_response.rb index 4001a16..d7e30a8 100644 --- a/lib/rack-cas/proxy_response.rb +++ b/lib/rack-cas/proxy_response.rb @@ -15,7 +15,7 @@ def initialize(url) def proxy_ticket if success? - xml.xpath('/cas:serviceResponse/cas:proxySuccess/cas:proxyTicket').text + xml.xpath('//serviceResponse/proxySuccess/proxyTicket').text else case failure_code when 'INVALID_REQUEST' @@ -33,11 +33,11 @@ def proxy_ticket protected def success? - @success ||= !!xml.at('/cas:serviceResponse/cas:proxySuccess') + @success ||= !!xml.at('//serviceResponse/proxySuccess') end def proxy_failure - @proxy_failure ||= xml.at('/cas:serviceResponse/cas:proxyFailure') + @proxy_failure ||= xml.at('//serviceResponse/proxyFailure') end def failure_message diff --git a/lib/rack-cas/service_validation_response.rb b/lib/rack-cas/service_validation_response.rb index 84371f9..3aba8f1 100644 --- a/lib/rack-cas/service_validation_response.rb +++ b/lib/rack-cas/service_validation_response.rb @@ -54,7 +54,7 @@ def extra_attributes def proxy_granting_ticket_iou if success? - @proxy_granting_ticket_iou ||= xml.at('/cas:serviceResponse/cas:authenticationSuccess/cas:proxyGrantingTicket').text + @proxy_granting_ticket_iou ||= xml.at('//serviceResponse/authenticationSuccess/proxyGrantingTicket').text end end From fa276a1c9a2b2e4d1b1b68995991dd57b0e24232 Mon Sep 17 00:00:00 2001 From: David Massad Date: Tue, 30 Aug 2016 12:59:24 -0500 Subject: [PATCH 08/13] Added cas namespace back to proxy_response.rb --- lib/rack-cas/proxy_response.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/rack-cas/proxy_response.rb b/lib/rack-cas/proxy_response.rb index d7e30a8..4001a16 100644 --- a/lib/rack-cas/proxy_response.rb +++ b/lib/rack-cas/proxy_response.rb @@ -15,7 +15,7 @@ def initialize(url) def proxy_ticket if success? - xml.xpath('//serviceResponse/proxySuccess/proxyTicket').text + xml.xpath('/cas:serviceResponse/cas:proxySuccess/cas:proxyTicket').text else case failure_code when 'INVALID_REQUEST' @@ -33,11 +33,11 @@ def proxy_ticket protected def success? - @success ||= !!xml.at('//serviceResponse/proxySuccess') + @success ||= !!xml.at('/cas:serviceResponse/cas:proxySuccess') end def proxy_failure - @proxy_failure ||= xml.at('//serviceResponse/proxyFailure') + @proxy_failure ||= xml.at('/cas:serviceResponse/cas:proxyFailure') end def failure_message From 9e7d11a6d2f28f9e77fb963c79d1652c673d69f7 Mon Sep 17 00:00:00 2001 From: David Massad Date: Tue, 30 Aug 2016 15:32:53 -0500 Subject: [PATCH 09/13] Prevent dropping duplicate query parameter names in the service URL. --- lib/rack-cas/url.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rack-cas/url.rb b/lib/rack-cas/url.rb index 01bd455..7e2964d 100644 --- a/lib/rack-cas/url.rb +++ b/lib/rack-cas/url.rb @@ -7,7 +7,7 @@ def self.parse(uri) # Addressable to replace + spaces with %20 spaces. Standardizing on %20 # should prevent service lookup issues due to encoding differences. super.tap do |u| - u.query_values = u.query_values + u.query_values = u.query_values(Array) end end From 7566ee011cbbfb12a00d74b3e1a1d47daecb9eb2 Mon Sep 17 00:00:00 2001 From: David Massad Date: Tue, 30 Aug 2016 15:53:55 -0500 Subject: [PATCH 10/13] Prevent dropping duplicate query parameter names in the service URL. --- lib/rack-cas/url.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/rack-cas/url.rb b/lib/rack-cas/url.rb index 7e2964d..b8ff898 100644 --- a/lib/rack-cas/url.rb +++ b/lib/rack-cas/url.rb @@ -19,9 +19,9 @@ def append_path(path) def add_params(params) self.tap do |u| - u.query_values = (u.query_values || {}).tap do |qv| + u.query_values = (u.query_values(Array) || []).tap do |qv| params.each do |key, value| - qv[key] = value + qv << [key, value] end end end @@ -34,9 +34,9 @@ def remove_param(param) # params can be an array or a hash def remove_params(params) self.tap do |u| - u.query_values = (u.query_values || {}).tap do |qv| + u.query_values = (u.query_values(Array) || []).tap do |qv| params.each do |key, value| - qv.delete key + qv.reject! { |param| param.first == key } end end if u.query_values.empty? From 00e7b4ee5e8ad1c82c698e25b5881d2c7d5ff232 Mon Sep 17 00:00:00 2001 From: David Massad Date: Tue, 30 Aug 2016 17:04:22 -0500 Subject: [PATCH 11/13] Allow minor updates to addressable gem. Updated urls in specs. --- rack-cas.gemspec | 2 +- spec/rack-cas/server_spec.rb | 4 ++-- spec/rack-cas/url_spec.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rack-cas.gemspec b/rack-cas.gemspec index ddf629a..c77bce8 100644 --- a/rack-cas.gemspec +++ b/rack-cas.gemspec @@ -15,7 +15,7 @@ spec = Gem::Specification.new do |s| s.homepage = 'https://github.com/biola/rack-cas' s.license = 'MIT' s.add_dependency 'rack', '>= 1.3' - s.add_dependency 'addressable', '~> 2.3' + s.add_dependency 'addressable', '~> 2' s.add_dependency 'nokogiri', '~> 1.5' s.add_development_dependency 'rspec', '~> 3.2' s.add_development_dependency 'rspec-its', '~> 1.0' diff --git a/spec/rack-cas/server_spec.rb b/spec/rack-cas/server_spec.rb index 36c733d..5670b4d 100644 --- a/spec/rack-cas/server_spec.rb +++ b/spec/rack-cas/server_spec.rb @@ -15,13 +15,13 @@ context 'with params' do subject { server.login_url(service_url, gateway: 'true') } - its(:to_s) { should eql 'http://example.com/cas/login?gateway=true&service=http%3A%2F%2Fexample.org%2Fwhatever' } + its(:to_s) { should eql 'http://example.com/cas/login?service=http%3A%2F%2Fexample.org%2Fwhatever&gateway=true' } end context 'with renew = true' do before { RackCAS.config.stub(renew: true) } subject { server.login_url(service_url) } - its(:to_s) { should eql 'http://example.com/cas/login?renew=true&service=http%3A%2F%2Fexample.org%2Fwhatever' } + its(:to_s) { should eql 'http://example.com/cas/login?service=http%3A%2F%2Fexample.org%2Fwhatever&renew=true' } end end diff --git a/spec/rack-cas/url_spec.rb b/spec/rack-cas/url_spec.rb index 2054417..6a6775f 100644 --- a/spec/rack-cas/url_spec.rb +++ b/spec/rack-cas/url_spec.rb @@ -19,7 +19,7 @@ describe :add_params do subject { url.add_params(appended: 'param') } - its(:query) { should eql 'appended=param¶m1=value1¶m2=value2' } + its(:query) { should eql 'param1=value1¶m2=value2&appended=param' } end describe :remove_param do From 7a04be7a7aad978ba6de0e86c6d67c201a06de12 Mon Sep 17 00:00:00 2001 From: Robert Taylor Date: Mon, 1 May 2023 11:26:26 -0500 Subject: [PATCH 12/13] Added rescue nil to proxyGrantingTicket validation --- lib/rack-cas/service_validation_response.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rack-cas/service_validation_response.rb b/lib/rack-cas/service_validation_response.rb index 3aba8f1..39e81ba 100644 --- a/lib/rack-cas/service_validation_response.rb +++ b/lib/rack-cas/service_validation_response.rb @@ -54,7 +54,7 @@ def extra_attributes def proxy_granting_ticket_iou if success? - @proxy_granting_ticket_iou ||= xml.at('//serviceResponse/authenticationSuccess/proxyGrantingTicket').text + @proxy_granting_ticket_iou ||= xml.at('//serviceResponse/authenticationSuccess/proxyGrantingTicket').text rescue nil end end From 3787c36d2edb62ffd367da3015192161d8189ef4 Mon Sep 17 00:00:00 2001 From: Robert Taylor Date: Fri, 5 May 2023 10:36:59 -0500 Subject: [PATCH 13/13] Update service_validation_response.rb to remove previous change --- lib/rack-cas/service_validation_response.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rack-cas/service_validation_response.rb b/lib/rack-cas/service_validation_response.rb index 39e81ba..3aba8f1 100644 --- a/lib/rack-cas/service_validation_response.rb +++ b/lib/rack-cas/service_validation_response.rb @@ -54,7 +54,7 @@ def extra_attributes def proxy_granting_ticket_iou if success? - @proxy_granting_ticket_iou ||= xml.at('//serviceResponse/authenticationSuccess/proxyGrantingTicket').text rescue nil + @proxy_granting_ticket_iou ||= xml.at('//serviceResponse/authenticationSuccess/proxyGrantingTicket').text end end