First cut at logout race detection in cache.
[shibboleth/cpp-sp.git] / shibsp / handler / impl / LocalLogoutInitiator.cpp
index 004af9f..aa51435 100644 (file)
@@ -45,9 +45,11 @@ namespace shibsp {
         LocalLogoutInitiator(const DOMElement* e, const char* appId);
         virtual ~LocalLogoutInitiator() {}
         
+        void setParent(const PropertySet* parent);
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
     private:
+        string m_appId;
         vector<Handler*> m_handlers;
     };
 
@@ -62,7 +64,7 @@ namespace shibsp {
 };
 
 LocalLogoutInitiator::LocalLogoutInitiator(const DOMElement* e, const char* appId)
-    : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".LogoutInitiator"))
+    : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".LogoutInitiator")), m_appId(appId)
 {
     pair<bool,const char*> loc = getString("Location");
     if (loc.first) {
@@ -71,6 +73,19 @@ LocalLogoutInitiator::LocalLogoutInitiator(const DOMElement* e, const char* appI
     }
 }
 
+void LocalLogoutInitiator::setParent(const PropertySet* parent)
+{
+    DOMPropertySet::setParent(parent);
+    pair<bool,const char*> loc = getString("Location");
+    if (loc.first) {
+        string address = m_appId + loc.second + "::run::LocalLI";
+        setAddress(address.c_str());
+    }
+    else {
+        m_log.warn("no Location property in Local LogoutInitiator (or parent), can't register as remoted handler");
+    }
+}
+
 pair<bool,long> LocalLogoutInitiator::run(SPRequest& request, bool isHandler) const
 {
     // Defer to base class first.
@@ -81,8 +96,15 @@ pair<bool,long> LocalLogoutInitiator::run(SPRequest& request, bool isHandler) co
     // Get session ID from cookie.
     pair<string,const char*> shib_cookie = request.getApplication().getCookieNameProps("_shibsession_");
     const char* session_id = request.getCookie(shib_cookie.first.c_str());
-    if (session_id)
+    if (session_id) {
+        // Do back channel notification.
+        vector<string> sessions(1, session_id);
+        if (!notifyBackChannel(request.getApplication(), request.getRequestURL(), sessions, true)) {
+            request.getApplication().getServiceProvider().getSessionCache()->remove(session_id, request.getApplication());
+            return sendLogoutPage(request.getApplication(), request, true, "Partial logout failure.");
+        }
         request.getServiceProvider().getSessionCache()->remove(session_id, request.getApplication());
+    }
 
     return sendLogoutPage(request.getApplication(), request, true, "Logout was successful.");
 }