 
     # -- Optional
     # Returns a redirect URL, at which a user is logged out.
-    create_logout_url: (identity_provider, name_id, session_index, cb) =>
+    create_logout_url: (identity_provider, name_id, session_index, relay_state..., cb) =>
+      relay_state = relay_state[0]
       xml = create_logout_request @issuer, name_id, session_index, identity_provider.sso_logout_url
       zlib.deflateRaw xml, (err, deflated) =>
         return cb err if err?
         uri = url.parse identity_provider.sso_logout_url
-        uri.query = sign_get_request deflated.toString('base64'), @private_key
+        uri.query = sign_get_request deflated.toString('base64'), @private_key, relay_state
         cb null, url.format(uri)
+
+    create_logout_response_url: (in_response_to, logout_url, cb) ->
+      xml = create_logout_response @issuer, "success", in_response_to, logout_url
+      zlib.deflateRaw xml, (err, deflated) =>
+        return cb err if err?
+        uri = url.parse logout_url
+        uri.query = sign_get_response deflated.toString('base64'), @private_key
+        cb null, url.format(uri)
+      # create_logout_response
 
     # Returns XML metadata, used during initial SAML configuration
     create_metadata: (assert_endpoint) =>

    assert: (identity_provider, request_body, get_request..., cb) ->
      get_request =  get_request[0]

      unless request_body?.SAMLResponse?
        return setImmediate cb, new Error("Request body does not contain SAMLResponse.")

      saml_response = null
      decrypted_assertion = null

# InResponseTo attributes of the Response if present. It will throw an error if the Response is missing or does not
# appear to be valid.
parse_response_header = (dom) ->
  for response_type in ['Response', 'LogoutResponse', 'LogoutRequest']
    response = dom.getElementsByTagNameNS(XMLNS.SAMLP, response_type)
    break if response.length > 0
  throw new Error("Expected 1 Response; found #{response.length}") unless response.length is 1
