lib/ciam/ruby-saml/logout_response.rb in ciam-es-0.0.6 vs lib/ciam/ruby-saml/logout_response.rb in ciam-es-0.0.7

- old
+ new

@@ -3,17 +3,19 @@ require "rexml/document" module Ciam module Saml class LogoutResponse - include Coding - include Request + include Coding + include Response ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion" PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol" DSIG = "http://www.w3.org/2000/09/xmldsig#" - def initialize( options = { } ) + attr_accessor :settings + + def initialize( options = { } ) opt = { :response => nil, :settings => nil }.merge(options) # We've recieved a LogoutResponse from the IdP if opt[:response] begin @response = Ciam::XMLSecurity::SignedDocument.new(decode( opt[:response] )) @@ -30,25 +32,26 @@ end # We plan to create() a new LogoutResponse if opt[:settings] @settings = opt[:settings] end - end + end # Create a LogoutResponse to to the IdP's LogoutRequest # (For IdP initiated SLO) def create( options ) opt = { :transaction_id => nil, :in_response_to => nil, :status => "urn:oasis:names:tc:SAML:2.0:status:Success", :extra_parameters => nil }.merge(options) return nil if opt[:transaction_id].nil? - @response = REXML::Document.new - @response.context[:attribute_quote] = :quote + response_doc = Ciam::XMLSecurityNew::Document.new + response_doc.context[:attribute_quote] = :quote + uuid = "_" + UUID.new.generate time = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ") - root = @response.add_element "saml2p:LogoutResponse", { "xmlns:saml2p" => PROTOCOL } + root = response_doc.add_element "saml2p:LogoutResponse", { "xmlns:saml2p" => PROTOCOL } root.attributes['ID'] = uuid root.attributes['IssueInstant'] = time root.attributes['Version'] = "2.0" # Just convenient naming to accept both names as InResponseTo if opt[:transaction_id] @@ -66,67 +69,82 @@ issuer = root.add_element "saml:Issuer", { "xmlns:saml" => "urn:oasis:names:tc:SAML:2.0:assertion" } issuer.text = @settings.issuer end - meta = Metadata.new( @settings ) - Logging.debug "Created LogoutResponse:\n#{@response}" - return meta.create_slo_response( to_s, opt[:extra_parameters] ) + + response_doc << REXML::XMLDecl.new("1.0", "UTF-8") + #sign logout_response + cert = @settings.get_cert(@settings.sp_cert) + + # embed signature + if @settings.metadata_signed && @settings.sp_private_key && @settings.sp_cert + private_key = @settings.get_sp_key + response_doc.sign_document(private_key, cert) + end - #root.attributes['Destination'] = action + Logging.debug "Created LogoutResponse:\n #{response_doc}" + return request_doc.to_s + end + # function to return the created request as an XML document def to_xml text = "" @response.write(text, 1) return text end + def to_s @response.to_s end - def issuer - element = REXML::XPath.first(@response, "/p:LogoutResponse/a:Issuer", { - "p" => PROTOCOL, "a" => ASSERTION} ) - return nil if element.nil? - element.text - end + def issuer + element = REXML::XPath.first(@response, "/p:LogoutResponse/a:Issuer", { + "p" => PROTOCOL, "a" => ASSERTION} ) + return nil if element.nil? + element.text + end - def in_response_to + def in_response_to element = REXML::XPath.first(@response, "/p:LogoutResponse", { "p" => PROTOCOL }) return nil if element.nil? - element.attributes["InResponseTo"] - end + element.attributes["InResponseTo"] + end - def success? + def success? element = REXML::XPath.first(@response, "/p:LogoutResponse/p:Status/p:StatusCode", { "p" => PROTOCOL }) return false if element.nil? - element.attributes["Value"] == "urn:oasis:names:tc:SAML:2.0:status:Success" - - end + element.attributes["Value"] == "urn:oasis:names:tc:SAML:2.0:status:Success" + + end + def is_valid? validate(soft = true) end def validate! validate( soft = false ) end + def validate( soft = true ) return false if @response.nil? # Skip validation with a failed response if we don't have settings return false if @settings.nil? return false if @response.validate(@settings, soft) == false return true end - protected + protected + def document REXML::Document.new(@response) end - end + + end end end