From 014431c749842c3ab953b5eaaf6553dbfbafc48a Mon Sep 17 00:00:00 2001 From: Annu Yadav Date: Fri, 25 Apr 2014 15:46:11 +0530 Subject: [PATCH 1/3] adding single logout feature. added logout action for IdpController with idp_slo_authenticate(email) and idp_make_saml_slo_response(person) methods. added saml_slo_post view. added validate_saml_slo_request, decode_SAML_SLO_Request and encode_SAML_SLO_Response methods in controller. --- app/controllers/saml_idp/idp_controller.rb | 23 ++++++++++ app/views/saml_idp/idp/saml_slo_post.html.erb | 13 ++++++ lib/saml_idp/controller.rb | 44 +++++++++++++++++-- 3 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 app/views/saml_idp/idp/saml_slo_post.html.erb diff --git a/app/controllers/saml_idp/idp_controller.rb b/app/controllers/saml_idp/idp_controller.rb index 603c249..be63cde 100644 --- a/app/controllers/saml_idp/idp_controller.rb +++ b/app/controllers/saml_idp/idp_controller.rb @@ -8,6 +8,8 @@ class IdpController < ActionController::Base protect_from_forgery before_filter :validate_saml_request + skip_before_filter :validate_saml_request, :only => [:logout] + before_filter :validate_saml_slo_request, :only => [:logout] def new render :template => "saml_idp/idp/new" @@ -27,6 +29,19 @@ def create render :template => "saml_idp/idp/new" end + def logout + _person, _logout = idp_slo_authenticate(params[:name_id]) + if _person && _logout + @saml_slo_response = idp_make_saml_slo_response(_person) + render :template => "saml_idp/idp/saml_slo_post", :layout => false + return + else + @saml_idp_fail_msg = 'Unable to logout' + logger.error 'Failed to logout' + end + render :nothing => true + end + protected def idp_authenticate(email, password) @@ -37,5 +52,13 @@ def idp_make_saml_response(person) raise "Not implemented" end + def idp_slo_authenticate(email) + raise "Not implemented" + end + + def idp_make_saml_slo_response(person) + raise "Not implemented" + end + end end diff --git a/app/views/saml_idp/idp/saml_slo_post.html.erb b/app/views/saml_idp/idp/saml_slo_post.html.erb new file mode 100644 index 0000000..dc5fb46 --- /dev/null +++ b/app/views/saml_idp/idp/saml_slo_post.html.erb @@ -0,0 +1,13 @@ + + + + + + + +<%= form_tag(@saml_slo_acs_url) do %> + <%= hidden_field_tag("SAMLResponse", @saml_slo_response) %> + <%= submit_tag "Submit" %> +<% end %> + + diff --git a/lib/saml_idp/controller.rb b/lib/saml_idp/controller.rb index 6eda6be..41dc9dc 100644 --- a/lib/saml_idp/controller.rb +++ b/lib/saml_idp/controller.rb @@ -81,12 +81,48 @@ def encode_SAMLResponse(nameID, opts = {}) Base64.encode64(xml) end + def validate_saml_slo_request(saml_request = params[:SAMLRequest]) + decode_SAML_SLO_Request(saml_request) + end + + def decode_SAML_SLO_Request(saml_request) + zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS) + @saml_slo_request = zstream.inflate(Base64.decode64(saml_request)) + zstream.finish + zstream.close + @saml_slo_request_id = @saml_slo_request[/ID=['"](.+?)['"]/, 1] + @saml_slo_acs_url = @saml_slo_request[/AssertionConsumerLogoutServiceURL=['"](.+?)['"]/, 1] + end + + def encode_SAML_SLO_Response(nameID, opts = {}) + now = Time.now.utc + response_id, reference_id = UUID.generate, UUID.generate + audience_uri = opts[:audience_uri] || @saml_slo_acs_url[/^(.*?\/\/.*?\/)/, 1] + issuer_uri = opts[:issuer_uri] || (defined?(request) && request.url.split("?")[0]) || "http://example.com" + + assertion = %[#{issuer_uri}#{nameID}#{audience_uri}#{nameID}urn:federation:authentication:windows] + + digest_value = Base64.encode64(algorithm.digest(assertion)).gsub(/\n/, '') + + signed_info = %[#{digest_value}] + + signature_value = sign(signed_info).gsub(/\n/, '') + + signature = %[#{signed_info}#{signature_value}#{self.x509_certificate}] + + assertion_and_signature = assertion.sub(/Issuer\>\#{signature}#{issuer_uri}#{assertion_and_signature}] + + Base64.encode64(xml) + end + private - def sign(data) - key = OpenSSL::PKey::RSA.new(self.secret_key) - Base64.encode64(key.sign(algorithm.new, data)) - end + def sign(data) + key = OpenSSL::PKey::RSA.new(self.secret_key) + Base64.encode64(key.sign(algorithm.new, data)) + end end end \ No newline at end of file From 7c187ed22db2dc83c3c30d40eab4cb783f99d174 Mon Sep 17 00:00:00 2001 From: Annu Yadav Date: Fri, 25 Apr 2014 16:41:26 +0530 Subject: [PATCH 2/3] giving response for every logout request. --- app/controllers/saml_idp/idp_controller.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/controllers/saml_idp/idp_controller.rb b/app/controllers/saml_idp/idp_controller.rb index be63cde..fadbf03 100644 --- a/app/controllers/saml_idp/idp_controller.rb +++ b/app/controllers/saml_idp/idp_controller.rb @@ -33,13 +33,12 @@ def logout _person, _logout = idp_slo_authenticate(params[:name_id]) if _person && _logout @saml_slo_response = idp_make_saml_slo_response(_person) - render :template => "saml_idp/idp/saml_slo_post", :layout => false - return else - @saml_idp_fail_msg = 'Unable to logout' - logger.error 'Failed to logout' + @saml_idp_fail_msg = 'User not found' + logger.error 'User with email #{params[:name_id]} not found' + @saml_slo_response = encode_SAML_SLO_Response(params[:name_id]) end - render :nothing => true + render :template => "saml_idp/idp/saml_slo_post", :layout => false end protected From fe7106e0becdbd01e8308c628c79d75d966e6259 Mon Sep 17 00:00:00 2001 From: Annu Yadav Date: Fri, 25 Apr 2014 16:52:40 +0530 Subject: [PATCH 3/3] giving response for every logout request. --- app/controllers/saml_idp/idp_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/saml_idp/idp_controller.rb b/app/controllers/saml_idp/idp_controller.rb index fadbf03..1080fc7 100644 --- a/app/controllers/saml_idp/idp_controller.rb +++ b/app/controllers/saml_idp/idp_controller.rb @@ -35,7 +35,7 @@ def logout @saml_slo_response = idp_make_saml_slo_response(_person) else @saml_idp_fail_msg = 'User not found' - logger.error 'User with email #{params[:name_id]} not found' + logger.error "User with email #{params[:name_id]} not found" @saml_slo_response = encode_SAML_SLO_Response(params[:name_id]) end render :template => "saml_idp/idp/saml_slo_post", :layout => false