diff options
Diffstat (limited to 'vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb')
-rw-r--r-- | vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb new file mode 100644 index 00000000000..72978227edb --- /dev/null +++ b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb @@ -0,0 +1,73 @@ +module OmniAuth + module Strategies + class CAS3 + class LogoutRequest + def initialize(strategy, request) + @strategy, @request = strategy, request + end + + def call(options = {}) + @options = options + + begin + result = single_sign_out_callback.call(*logout_request) + rescue StandardError => err + return @strategy.fail! :logout_request, err + else + result = [200,{},'OK'] if result == true || result.nil? + ensure + return unless result + + # TODO: Why does ActionPack::Response return [status,headers,body] + # when Rack::Response#new wants [body,status,headers]? Additionally, + # why does Rack::Response differ in argument order from the usual + # Rack-like [status,headers,body] array? + return Rack::Response.new(result[2],result[0],result[1]).finish + end + end + + private + + def logout_request + @logout_request ||= begin + saml = parse_and_ensure_namespaces(@request.params['logoutRequest']) + ns = saml.collect_namespaces + name_id = saml.xpath('//saml:NameID', ns).text + sess_idx = saml.xpath('//samlp:SessionIndex', ns).text + inject_params(name_id:name_id, session_index:sess_idx) + @request + end + end + + def parse_and_ensure_namespaces(logout_request_xml) + doc = Nokogiri.parse(logout_request_xml) + ns = doc.collect_namespaces + if ns.include?('xmlns:samlp') && ns.include?('xmlns:saml') + doc + else + add_namespaces(doc) + end + end + + def add_namespaces(logout_request_doc) + root = logout_request_doc.root + root.add_namespace('samlp', 'urn:oasis:names:tc:SAML:2.0:protocol') + root.add_namespace('saml', 'urn:oasis:names:tc:SAML:2.0:assertion\\') + + # In order to add namespaces properly we need to re-parse the document + Nokogiri.parse(logout_request_doc.to_s) + end + + def inject_params(new_params) + new_params.each do |key, val| + @request.update_param(key, val) + end + end + + def single_sign_out_callback + @options[:on_single_sign_out] + end + end + end + end +end |